From 43db722ece0e11cf1e6d2309d1fcac0bec0dbe30 Mon Sep 17 00:00:00 2001 From: DrSlony Date: Sun, 22 Feb 2015 01:35:30 +0100 Subject: [PATCH] Issue 2594: My kingdom for more wavelets - various speedups, memory reductions, GUI changes and level numbering PP3 change. --- rtdata/languages/default | 159 ++--- rtengine/cplx_wavelet_dec.cc | 7 +- rtengine/cplx_wavelet_dec.h | 160 +++-- rtengine/cplx_wavelet_filter_coeffs.h | 11 +- rtengine/cplx_wavelet_level.h | 483 +++++++-------- rtengine/dcrop.cc | 19 +- rtengine/improcfun.h | 4 +- rtengine/ipwavelet.cc | 848 ++++++++++++++++---------- rtengine/procevents.h | 5 +- rtengine/procparams.cc | 46 +- rtengine/procparams.h | 7 +- rtengine/refreshmap.cc | 5 +- rtengine/settings.h | 2 +- rtgui/addsetids.h | 8 +- rtgui/batchtoolpanelcoord.cc | 10 +- rtgui/options.cc | 9 +- rtgui/paramsedited.cc | 22 +- rtgui/paramsedited.h | 7 +- rtgui/preferences.cc | 30 +- rtgui/preferences.h | 7 +- rtgui/wavelet.cc | 345 +++++++---- rtgui/wavelet.h | 30 +- 22 files changed, 1316 insertions(+), 908 deletions(-) diff --git a/rtdata/languages/default b/rtdata/languages/default index 47fdb1bc1..7a05e369d 100644 --- a/rtdata/languages/default +++ b/rtdata/languages/default @@ -520,30 +520,30 @@ HISTORY_MSG_300;- HISTORY_MSG_301;NR - Luma control HISTORY_MSG_302;NR - Chroma method HISTORY_MSG_303;NR - Chroma method -HISTORY_MSG_304;Wavelet level -HISTORY_MSG_305;Wavelet level +HISTORY_MSG_304;Wavelet Level +HISTORY_MSG_305;Wavelet Level HISTORY_MSG_306;Wavelet N° level HISTORY_MSG_307;Wavelet Ch level -HISTORY_MSG_308;Wavelet direction -HISTORY_MSG_309;Wavelet tiles +HISTORY_MSG_308;Wavelet Direction +HISTORY_MSG_309;Wavelet Edge threshold HISTORY_MSG_310;Wavelet Hue-tones sky HISTORY_MSG_311;Wavelet Max Levels -HISTORY_MSG_312;Wavelet Shadow Threshold +HISTORY_MSG_312;Wavelet Shadow Threshold HISTORY_MSG_313;Wavelet Pastel Saturated -HISTORY_MSG_314;Wavelet artifacts blue sky +HISTORY_MSG_314;Wavelet Artifacts blue sky HISTORY_MSG_315;Wavelet Contrast Residual HISTORY_MSG_316;Wavelet Skin tones HISTORY_MSG_317;Wavelet Skin hue -HISTORY_MSG_318;Wavelet highlight levels -HISTORY_MSG_319;Wavelet highlight range -HISTORY_MSG_320;Wavelet shadow range -HISTORY_MSG_321;Wavelet shadow levels -HISTORY_MSG_322;Wavelet avoid color shift -HISTORY_MSG_323;Wavelet Chroma level -HISTORY_MSG_324;Wavelet Chroma pastel -HISTORY_MSG_325;Wavelet Chroma saturated -HISTORY_MSG_326;Wavelet Chroma method -HISTORY_MSG_327;Wavelet Contrast method +HISTORY_MSG_318;Wavelet Highlight levels +HISTORY_MSG_319;Wavelet Highlight range +HISTORY_MSG_320;Wavelet Shadow range +HISTORY_MSG_321;Wavelet Shadow levels +HISTORY_MSG_322;Wavelet Avoid color shift +HISTORY_MSG_323;Wavelet Chroma level +HISTORY_MSG_324;Wavelet Chroma pastel +HISTORY_MSG_325;Wavelet Chroma saturated +HISTORY_MSG_326;Wavelet Chroma method +HISTORY_MSG_327;Wavelet Contrast method HISTORY_MSG_328;Wavelet Chroma link HISTORY_MSG_329;Wavelet Opacity RG HISTORY_MSG_330;Wavelet Opacity BY @@ -554,6 +554,9 @@ HISTORY_MSG_334;Wavelet Chroma HISTORY_MSG_335;Wavelet Highlight Residual HISTORY_MSG_336;Wavelet Highlight threshold HISTORY_MSG_337;Wavelet Hue range +HISTORY_MSG_338;Wavelet Edge Radius +HISTORY_MSG_339;Wavelet Edge Value +HISTORY_MSG_340;Wavelet Strength HISTORY_NEWSNAPSHOT;Add HISTORY_NEWSNAPSHOT_TOOLTIP;Shortcut: Alt-s HISTORY_SNAPSHOTS;Snapshots @@ -751,8 +754,8 @@ PARTIALPASTE_VIBRANCE;Vibrance PARTIALPASTE_VIGNETTING;Vignetting correction PARTIALPASTE_WHITEBALANCE;White balance PREFERENCES_ADD;Add -PREFERENCES_APPLNEXTSTARTUP;restart required PREFERENCES_APPLNEXTRELOAD;image reload required +PREFERENCES_APPLNEXTSTARTUP;restart required PREFERENCES_AUTLISLOW;Low PREFERENCES_AUTLISMAX;Max - Average of all tiles PREFERENCES_AUTLISSTD;High @@ -761,11 +764,11 @@ PREFERENCES_AUTLOW;Low PREFERENCES_AUTOMONPROFILE;Use operating system's main monitor color profile PREFERENCES_AUTSTD;Standard PREFERENCES_BATCH_PROCESSING;Batch Processing -PREFERENCES_BEHADDALLHINT;Set all parameters to the Add mode.\nAdjustments of parameters in the batch tool panel will be deltas to the stored values. PREFERENCES_BEHADDALL;All to 'Add' +PREFERENCES_BEHADDALLHINT;Set all parameters to the Add mode.\nAdjustments of parameters in the batch tool panel will be deltas to the stored values. PREFERENCES_BEHAVIOR;Behavior -PREFERENCES_BEHSETALLHINT;Set all parameters to the Set mode.\nAdjustments of parameters in the batch tool panel will be absolute, the actual values will be displayed. PREFERENCES_BEHSETALL;All to 'Set' +PREFERENCES_BEHSETALLHINT;Set all parameters to the Set mode.\nAdjustments of parameters in the batch tool panel will be absolute, the actual values will be displayed. PREFERENCES_BLACKBODY;Tungsten PREFERENCES_CACHECLEARALL;Clear All PREFERENCES_CACHECLEARPROFILES;Clear Processing Profiles @@ -782,29 +785,27 @@ PREFERENCES_CLUTSCACHE;HaldCLUT Cache PREFERENCES_CLUTSCACHE_LABEL;Maximum number of cached CLUTs PREFERENCES_CLUTSDIR;HaldCLUT directory PREFERENCES_CMETRICINTENT;Colorimetric intent +PREFERENCES_CUSTPROFBUILD;Custom Processing Profile Builder PREFERENCES_CUSTPROFBUILDHINT;Executable (or script) file called when a new initial processing profile should be generated for an image.\n\nThe path of the communication file (*.ini style, a.k.a. "Keyfile") is added as a command line parameter. It contains various parameters required for the scripts and image Exif to allow a rules-based processing profile generation.\n\nWARNING: You are responsible for using double quotes where necessary if you're using paths containing spaces. PREFERENCES_CUSTPROFBUILDKEYFORMAT;Keys format PREFERENCES_CUSTPROFBUILDKEYFORMAT_NAME;Name PREFERENCES_CUSTPROFBUILDKEYFORMAT_TID;TagID PREFERENCES_CUSTPROFBUILDPATH;Executable path -PREFERENCES_CUSTPROFBUILD;Custom Processing Profile Builder PREFERENCES_CUTOVERLAYBRUSH;Crop mask color/transparency PREFERENCES_D50;5000K PREFERENCES_D55;5500K PREFERENCES_D60;6000K PREFERENCES_D65;6500K +PREFERENCES_DARKFRAME;Dark-Frame PREFERENCES_DARKFRAMEFOUND;Found PREFERENCES_DARKFRAMESHOTS;shots PREFERENCES_DARKFRAMETEMPLATES;templates -PREFERENCES_DARKFRAME;Dark-Frame -PREFERENCES_DATEFORMATHINT;You can use the following formatting strings:\n%y - year\n%m - month\n%d - day\n\nFor example, the ISO 8601 standard dictates the date format as follows:\n%y-%m-%d PREFERENCES_DATEFORMAT;Date format +PREFERENCES_DATEFORMATHINT;You can use the following formatting strings:\n%y - year\n%m - month\n%d - day\n\nFor example, the ISO 8601 standard dictates the date format as follows:\n%y-%m-%d +PREFERENCES_DAUB_LABEL;Use Daubechies D6 wavelets instead of D4 +PREFERENCES_DAUB_TOOLTIP;The Noise Reduction and Wavelet Levels tools use a Debauchies mother wavelet. If you choose D6 instead of D4 you increase the number of orthogonal Daubechies coefficients and probably increase quality of small-scale levels. There is no memory or processing time difference between the two. PREFERENCES_DEFAULTLANG;Default Language PREFERENCES_DEFAULTTHEME;Default Theme -PREFERENCES_PREVDEMO;Preview Demosaic Method -PREFERENCES_PREVDEMO_LABEL;Demosaicing method used for the preview at <100% zoom: -PREFERENCES_PREVDEMO_FAST;Fast -PREFERENCES_PREVDEMO_SIDECAR;As in PP3 PREFERENCES_DIRDARKFRAMES;Dark-frames directory PREFERENCES_DIRHOME;Home directory PREFERENCES_DIRLAST;Last visited directory @@ -819,14 +820,14 @@ PREFERENCES_FBROWSEROPTS;File Browser / Thumbnail Options PREFERENCES_FILEBROWSERTOOLBARSINGLEROW;Single row file browser toolbar (de-select for low resolution display) PREFERENCES_FILEFORMAT;File format PREFERENCES_FILMSIMULATION;Film Simulation +PREFERENCES_FLATFIELD;Flat-Field PREFERENCES_FLATFIELDFOUND;Found PREFERENCES_FLATFIELDSDIR;Flat-fields directory PREFERENCES_FLATFIELDSHOTS;shots PREFERENCES_FLATFIELDTEMPLATES;templates -PREFERENCES_FLATFIELD;Flat-Field +PREFERENCES_FLUOF11;Fluorescent F11 PREFERENCES_FLUOF2;Fluorescent F2 PREFERENCES_FLUOF7;Fluorescent F7 -PREFERENCES_FLUOF11;Fluorescent F11 PREFERENCES_FORIMAGE;For non-raw photos PREFERENCES_FORRAW;For raw photos PREFERENCES_FSTRIP_SAME_THUMB_HEIGHT;Same thumbnail height between the Editor's panel and the File Browser @@ -839,10 +840,10 @@ PREFERENCES_GREY18;Yb=18 CIE L#50 PREFERENCES_GREY23;Yb=23 CIE L#55 PREFERENCES_GREY30;Yb=30 CIE L#60 PREFERENCES_GREY40;Yb=40 CIE L#70 -PREFERENCES_GREYSC18;Yb=18 CIE L#50 -PREFERENCES_GREYSCA;Automatic -PREFERENCES_GREYSC;Scene Yb luminance (%) PREFERENCES_GREY;Output device's Yb luminance (%) +PREFERENCES_GREYSC18;Yb=18 CIE L#50 +PREFERENCES_GREYSC;Scene Yb luminance (%) +PREFERENCES_GREYSCA;Automatic PREFERENCES_HISTOGRAMPOSITIONLEFT;Histogram in left panel PREFERENCES_HISTOGRAMWORKING;Use working profile for main histogram and Navigator PREFERENCES_HISTOGRAM_TOOLTIP;If enabled, the working profile is used for rendering the main histogram and the Navigator panel, otherwise the gamma-corrected output profile is used. @@ -873,24 +874,28 @@ PREFERENCES_MENUOPTIONS;Context Menu Options PREFERENCES_METADATA;Metadata PREFERENCES_MIN;Mini (100x115) PREFERENCES_MONITORICC;Monitor color profile -PREFERENCES_MULTITABDUALMON;Multiple Editor Tabs In Own Window Mode PREFERENCES_MULTITAB;Multiple Editor Tabs Mode +PREFERENCES_MULTITABDUALMON;Multiple Editor Tabs In Own Window Mode PREFERENCES_NAVGUIDEBRUSH;Navigator guide color PREFERENCES_NOISE;Noise Reduction -PREFERENCES_OUTDIRFOLDERHINT;Save images to the selected folder. -PREFERENCES_OUTDIRFOLDER;Save to folder -PREFERENCES_OUTDIRTEMPLATEHINT;You can use the following formatting strings:\n%f, %d1, %d2, ..., %p1, %p2, ..., %r, %s1, %s2, ...\n\nThese formatting strings refer to the different parts of the photo's pathname, some attributes of the photo or an arbitrary sequence index in the batch job.\n\nFor example, if the photo being processed has the following pathname:\n/home/tom/photos/2010-10-31/dsc0042.nef\nthe meaning of the formatting strings are:\n%d4 = home\n%d3 = tom\n%d2 = photos\n%d1 = 2010-10-31\n%f = dsc0042\n%p1 = /home/tom/photos/2010-10-31/\n%p2 = /home/tom/photos/\n%p3 = /home/tom/\n%p4 = /home/\n\n%r will be replaced by the rank of the photo. If the photo is unranked, %r will be replaced by '0'. If the photo is in the trash bin, %r will be replaced by 'x'.\n\n%s1, %s2, etc. will be replaced by a sequence index which is padded to between 1 and 9 digits. The sequence index will start at one each time the queue processing is started and is incremented by one for each image processed.\n\nIf you want to save the output image where the original is, write:\n%p1/%f\n\nIf you want to save the output image in a directory named "converted" located in the directory of the opened image, write:\n%p1/converted/%f\n\nIf you want to save the output image in a directory named "/home/tom/photos/converted/2010-10-31", write:\n%p2/converted/%d1/%f -PREFERENCES_OUTDIRTEMPLATE;Use template PREFERENCES_OUTDIR;Output Directory +PREFERENCES_OUTDIRFOLDER;Save to folder +PREFERENCES_OUTDIRFOLDERHINT;Save images to the selected folder. +PREFERENCES_OUTDIRTEMPLATE;Use template +PREFERENCES_OUTDIRTEMPLATEHINT;You can use the following formatting strings:\n%f, %d1, %d2, ..., %p1, %p2, ..., %r, %s1, %s2, ...\n\nThese formatting strings refer to the different parts of the photo's pathname, some attributes of the photo or an arbitrary sequence index in the batch job.\n\nFor example, if the photo being processed has the following pathname:\n/home/tom/photos/2010-10-31/dsc0042.nef\nthe meaning of the formatting strings are:\n%d4 = home\n%d3 = tom\n%d2 = photos\n%d1 = 2010-10-31\n%f = dsc0042\n%p1 = /home/tom/photos/2010-10-31/\n%p2 = /home/tom/photos/\n%p3 = /home/tom/\n%p4 = /home/\n\n%r will be replaced by the rank of the photo. If the photo is unranked, %r will be replaced by '0'. If the photo is in the trash bin, %r will be replaced by 'x'.\n\n%s1, %s2, etc. will be replaced by a sequence index which is padded to between 1 and 9 digits. The sequence index will start at one each time the queue processing is started and is incremented by one for each image processed.\n\nIf you want to save the output image where the original is, write:\n%p1/%f\n\nIf you want to save the output image in a directory named "converted" located in the directory of the opened image, write:\n%p1/converted/%f\n\nIf you want to save the output image in a directory named "/home/tom/photos/converted/2010-10-31", write:\n%p2/converted/%d1/%f PREFERENCES_OVERLAY_FILENAMES;Overlay filenames on thumbnails in the file browser PREFERENCES_OVERLAY_FILENAMES_FILMSTRIP;Overlay filenames on thumbnails in the editor pannel PREFERENCES_OVERWRITEOUTPUTFILE;Overwrite existing output files PREFERENCES_PANFACTORFRAME;Pan Rate Amplification PREFERENCES_PANFACTORLABEL;Factor -PREFERENCES_PARSEDEXTADDHINT;Add entered extension to the list. -PREFERENCES_PARSEDEXTADD;Add extension -PREFERENCES_PARSEDEXTDELHINT;Delete selected extension from the list. PREFERENCES_PARSEDEXT;Parsed Extensions +PREFERENCES_PARSEDEXTADD;Add extension +PREFERENCES_PARSEDEXTADDHINT;Add entered extension to the list. +PREFERENCES_PARSEDEXTDELHINT;Delete selected extension from the list. +PREFERENCES_PREVDEMO;Preview Demosaic Method +PREFERENCES_PREVDEMO_FAST;Fast +PREFERENCES_PREVDEMO_LABEL;Demosaicing method used for the preview at <100% zoom: +PREFERENCES_PREVDEMO_SIDECAR;As in PP3 PREFERENCES_PROFILEHANDLING;Processing Profile Handling PREFERENCES_PROFILELOADPR;Processing profile loading priority PREFERENCES_PROFILEPRCACHE;Profile in cache @@ -899,8 +904,8 @@ PREFERENCES_PROFILESAVECACHE;Save processing profile to the cache PREFERENCES_PROFILESAVEINPUT;Save processing profile next to the input file PREFERENCES_PROPERTY;Property PREFERENCES_PSPATH;Adobe Photoshop installation directory -PREFERENCES_RGBDTL_LABEL;Max number of threads Denoise and Wavelet (divide by 2) -PREFERENCES_RGBDTL_TOOLTIP;Noise Reduction and Wavelet requires a baseline of about 128MB RAM for a 10MPix image or 512MB for a 40MPix image, and additionally 128MB RAM per thread. The more threads run in parallel, the faster the computation. Leave the setting at "0" to automatically use as many threads as possible. +PREFERENCES_RGBDTL_LABEL;Max number of threads for Noise Reduction and Wavelet Levels +PREFERENCES_RGBDTL_TOOLTIP;Leave the setting at "0" to automatically use as many threads as possible. The more threads run in parallel, the faster the computation. Refer to RawPedia for memory requirements. PREFERENCES_SELECTFONT;Select font PREFERENCES_SELECTLANG;Select language PREFERENCES_SELECTTHEME;Select theme @@ -912,12 +917,12 @@ PREFERENCES_SHOWFILMSTRIPTOOLBAR;Show filmstrip toolbar PREFERENCES_SHOWPROFILESELECTOR;Show processing profile selector PREFERENCES_SHTHRESHOLD;Threshold for clipped shadows PREFERENCES_SIMPLAUT;Tool mode -PREFERENCES_SINGLETABVERTAB;Single Editor Tab Mode, Vertical Tabs PREFERENCES_SINGLETAB;Single Editor Tab Mode +PREFERENCES_SINGLETABVERTAB;Single Editor Tab Mode, Vertical Tabs PREFERENCES_SLIMUI;Slim interface PREFERENCES_SMA;Small (250x287) PREFERENCES_SND_BATCHQUEUEDONE;Queue processing done -PREFERENCES_SND_HELP;Either enter filepath or nothing (for no sound).\nOn Windows use "SystemDefault", "SystemAsterisk" etc. for system sounds.\nOn Linux use "complete", "window-attention" etc. for system sounds. +PREFERENCES_SND_HELP;Enter a full file path to set a sound, or leave blank for no sound.\nFor system sounds on Windows use "SystemDefault", "SystemAsterisk" etc., and on Linux use "complete", "window-attention" etc. PREFERENCES_SND_LNGEDITPROCDONE;Editor processing done PREFERENCES_SND_TRESHOLDSECS;After seconds PREFERENCES_STARTUPIMDIR;Image Directory at Startup @@ -1278,6 +1283,10 @@ TP_DIRPYRDENOISE_SHALBI;High TP_DIRPYRDENOISE_SHAL;Standard TP_DIRPYRDENOISE_SLI;Slider TP_DIRPYRDENOISE_SOFT;3x3 +TP_WAVELET_EDGE;Edge Sharpness (Luminance) +TP_WAVELET_EDRAD;Radius +TP_WAVELET_EDVAL;Value +TP_WAVELET_EDGTHRESH;Threshold TP_WAVELET_RESID;Residual image TP_WAVELET_RESCON;Shadows TP_WAVELET_RESCONH;Highlights @@ -1297,63 +1306,61 @@ TP_WAVELET_OPACITY;Opacity Blue-Yellow Levels TP_WAVELET_CONTR;Gamut - controls TP_WAVELET_UTIL;Utilities TP_WAVELET_CONTRA_TOOLTIP;Change contrast residual image\nFunction of Max Levels -TP_WAVELET_DISP;Display Wavelet levels +TP_WAVELET_DISP;Preview Settings +TP_WAVELET_SETTINGS;Wavelet Settings TP_WAVELET_DISPLAY;Levels and Utilities TP_WAVELET_DISPLAYCHRO;Chromaticity and Toning TP_WAVELET_DISPLAYGAM;Gamut and Control TP_DIRPYRDENOISE_TILELABEL;Tile size=%1, Center: Tx=%2 Ty=%3 +TP_WAVELET_PREVIEWLEVELS;Preview TP_WAVELET_CONTRAST_MINUS;Contrast - TP_WAVELET_NEUTRAL;Neutral TP_WAVELET_CONTRAST_PLUS;Contrast + TP_WAVELET_FINEST;Finest TP_WAVELET_LARGEST;Coarsest TP_WAVELET_LABEL;Wavelet levels -TP_WAVELET_ONE;one level -TP_WAVELET_INF;below or equal the level -TP_WAVELET_SUP;above the level + residual +TP_WAVELET_ONE;One level +TP_WAVELET_INF;Below or equal the level +TP_WAVELET_SUP;Above the level TP_WAVELET_SUPE;Extra -TP_WAVELET_ALL;all levels-directions -TP_WAVELET_0;level 0 -TP_WAVELET_1;level 1 -TP_WAVELET_2;level 2 -TP_WAVELET_3;level 3 -TP_WAVELET_4;level 4 -TP_WAVELET_5;level 5 -TP_WAVELET_6;level 6 -TP_WAVELET_7;level 7 -TP_WAVELET_8;level 8 +TP_WAVELET_ALL;All levels in all directions +TP_WAVELET_1;Level 1 +TP_WAVELET_2;Level 2 +TP_WAVELET_3;Level 3 +TP_WAVELET_4;Level 4 +TP_WAVELET_5;Level 5 +TP_WAVELET_6;Level 6 +TP_WAVELET_7;Level 7 +TP_WAVELET_8;Level 8 +TP_WAVELET_9;Level 9 TP_WAVELET_LEVLABEL;Preview maximum possible levels=%1 TP_WAVELET_AVOID;Avoid color shift -TP_WAVELET_DONE;Direction: Vertical -TP_WAVELET_DTWO;Direction: Horizontal -TP_WAVELET_DTHR;Direction: Diagonal +TP_WAVELET_DONE;Vertical +TP_WAVELET_DTWO;Horizontal +TP_WAVELET_DTHR;Diagonal TP_WAVELET_DALL;All directions +TP_WAVELET_APPLYTO;Apply To TP_WAVELET_MEDI;Reduce artifacts in blue sky -TP_WAVELET_THRES;Max level -TP_WAVELET_THRES_TOOLTIP;Can act on the number of active levels. Levels higher values are not taken into account, regardless of the position of the slider. -TP_WAVELET_TILES;Tiles size (* 128) -TP_WAVELET_TILES_TOOLTIP;If you select full image process will be performed - for a 16M image and 10 levels this option needs memory 2.G°\nfor a 24M image and 10 levels this option needs memory 2.5G°\nfor a 35M image and 10 levels this option needs memory 3.3G°\nOtherwise select tiles or if memory is too low -TP_WAVELET_TILESFULL;Full image -TP_WAVELET_TILESBIG;Big Tiles -TP_WAVELET_TILESLIT;Little Tiles +TP_WAVELET_LEVELS;Wavelet levels +TP_WAVELET_LEVELS_TOOLTIP;Choose the number of detail levels the image is to be decomposed into. More levels require more RAM and require a longer processing time. TP_WAVELET_CHRO;Saturated - Pastel TP_WAVELET_CHR;Chroma link TP_WAVELET_CHR_TOOLTIP;Adjust chroma in function of:\na-levels contrasts\nb-Chroma link slider strength TP_WAVELET_CHRO_TOOLTIP;Limit between pastel and saturated\n 1-x level saturated \n x-9 level pastel -TP_WAVELET_THRESHOLD;Highlight Levels numbers used (finest to coarsest - master) +TP_WAVELET_THRESHOLD;Highlight levels TP_WAVELET_THRESHOLD_TOOLTIP;If you change this value, only level beyond will be treated with highlight luminance levels\nOthers level will be full treated TP_WAVELET_THRESHOLD2_TOOLTIP;If you change this value, only level between 9 and 9 minus value, will be treated with shadow luminance levels\nOthers level will be full treated\nMax level shadow is limited by value of highlight level (9-highlight level) TP_WAVELET_HIGHSHA;Highlight Shadows -TP_WAVELET_HIGHLIGHT;Highlight Luminance Range (0..100) -TP_WAVELET_THRESHOLD2;Shadows Levels numbers used(coarsest to finest) -TP_WAVELET_LOWLIGHT;Shadow Luminance Range (0..100) +TP_WAVELET_HIGHLIGHT;Highlight luminance range +TP_WAVELET_THRESHOLD2;Shadow Levels +TP_WAVELET_LOWLIGHT;Shadow luminance range TP_WAVELET_PASTEL;Pastel chromacity TP_WAVELET_SAT;Saturated chromacity TP_WAVELET_CH1;All chroma TP_WAVELET_CH2;Pastel - Saturated TP_WAVELET_CH3;Link contrast levels -TP_WAVELET_HS1;All luminance -TP_WAVELET_HS2;Highlight - Shadows +TP_WAVELET_HS1;Whole luminance range +TP_WAVELET_HS2;Shadows/Highlights TP_WAVELET_MIN;min TP_WAVELET_MAX;max TP_WAVELET_CLVCURVE;Chrominance - Levels @@ -1362,6 +1369,12 @@ TP_WAVELET_HUESKIN;Hue Range (skin) TP_WAVELET_HUESKIN_TOOLTIP;This pyramid is for the upper part, so far as the algorithm at its maximum efficiency.\nTo the lower part, the transition zones.\nIf you need to move the area significantly to the left or right - or if there are artifacts: the white balance is incorrect\nYou can slightly reduce the zone to prevent the rest of the image is affected. TP_WAVELET_SKIN;Hue-tones (skin) targetting/protection TP_WAVELET_SKIN_TOOLTIP;At -100 skin-tones are targetted.\nAt 0 all tones are treated equally.\nAt +100 skin-tones are protected while all other tones are affected. +TP_WAVELET_STRENGTH;Strength +TP_WAVELET_TILESBIG;Big tiles +TP_WAVELET_TILESFULL;Full image +TP_WAVELET_TILESIZE;Tile size +TP_WAVELET_TILESLIT;Little tiles +TP_WAVELET_TILES_TOOLTIP;Processing the full image leads to better quality and is the recommended option, while using tiles is a fall-back solution for users with little RAM. Refer to RawPedia for memory requirements. TP_DIRPYREQUALIZER_ALGO;Skin Color Range TP_DIRPYREQUALIZER_ALGO_TOOLTIP;Fine: closer to the colors of the skin, minimizing the action on other colors\nLarge: avoid more artifacts. TP_DIRPYREQUALIZER_GAMUT;Reduce artifacts diff --git a/rtengine/cplx_wavelet_dec.cc b/rtengine/cplx_wavelet_dec.cc index 9c4d77ab6..4a35cd371 100644 --- a/rtengine/cplx_wavelet_dec.cc +++ b/rtengine/cplx_wavelet_dec.cc @@ -25,11 +25,12 @@ namespace rtengine { wavelet_decomposition::~wavelet_decomposition() { for(int i = 0; i <= lvltot; i++) { - delete wavelet_decomp[i]; + if(wavelet_decomp[i] != NULL) + delete wavelet_decomp[i]; } delete[] wavfilt_anal; - delete[] wavfilt_synth; - if(coeff0) + delete[] wavfilt_synth; + if(coeff0) delete [] coeff0; } diff --git a/rtengine/cplx_wavelet_dec.h b/rtengine/cplx_wavelet_dec.h index 31811ca9b..62219c5fd 100644 --- a/rtengine/cplx_wavelet_dec.h +++ b/rtengine/cplx_wavelet_dec.h @@ -25,7 +25,7 @@ #include #include "cplx_wavelet_level.h" -#include "cplx_wavelet_filter_coeffs.h" +#include "cplx_wavelet_filter_coeffs.h" namespace rtengine { @@ -34,14 +34,14 @@ namespace rtengine { public: typedef float internal_type; - float *coeff0; + float *coeff0; bool memoryAllocationFailed; private: static const int maxlevels = 10;//should be greater than any conceivable order of decimation - int lvltot, subsamp; + int lvltot, subsamp; int numThreads; int m_w, m_h;//dimensions @@ -55,7 +55,7 @@ namespace rtengine { public: template - wavelet_decomposition(E * src, int width, int height, int maxlvl, int subsampling, int skipcrop = 1, int numThreads = 1); + wavelet_decomposition(E * src, int width, int height, int maxlvl, int subsampling, int skipcrop = 1, int numThreads = 1, int Daub4Len = 6); ~wavelet_decomposition(); @@ -89,99 +89,129 @@ namespace rtengine { return subsamp; } template - void reconstruct(E * dst); + void reconstruct(E * dst, const float blend = 1.f); }; template - wavelet_decomposition::wavelet_decomposition(E * src, int width, int height, int maxlvl, int subsampling, int skipcrop, int numThreads) + wavelet_decomposition::wavelet_decomposition(E * src, int width, int height, int maxlvl, int subsampling, int skipcrop, int numThreads, int Daub4Len) : coeff0(NULL), memoryAllocationFailed(false), lvltot(0), subsamp(subsampling), numThreads(numThreads), m_w(width), m_h(height) { + //initialize wavelet filters - wavfilt_len = Daub4_len; + wavfilt_len = Daub4Len; wavfilt_offset = Daub4_offset; wavfilt_anal = new float[2*wavfilt_len]; wavfilt_synth = new float[2*wavfilt_len]; - for (int n=0; n<2; n++) { - for (int i=0; i(src, buffer[bufferindex^1], lvltot/*level*/, subsamp, m_w, m_h, \ - wavfilt_anal, wavfilt_anal, wavfilt_len, wavfilt_offset, skipcrop, numThreads); - if(wavelet_decomp[lvltot]->memoryAllocationFailed) - memoryAllocationFailed = true; + wavfilt_anal, wavfilt_anal, wavfilt_len, wavfilt_offset, skipcrop, numThreads); + if(wavelet_decomp[lvltot]->memoryAllocationFailed) + memoryAllocationFailed = true; while(lvltot < maxlvl-1) { lvltot++; bufferindex ^= 1; wavelet_decomp[lvltot] = new wavelet_level(buffer[bufferindex], buffer[bufferindex^1]/*lopass*/, lvltot/*level*/, subsamp, \ wavelet_decomp[lvltot-1]->width(), wavelet_decomp[lvltot-1]->height(), \ - wavfilt_anal, wavfilt_anal, wavfilt_len, wavfilt_offset, skipcrop, numThreads); - if(wavelet_decomp[lvltot]->memoryAllocationFailed) - memoryAllocationFailed = true; - } - coeff0 = buffer[bufferindex^1]; + wavfilt_anal, wavfilt_anal, wavfilt_len, wavfilt_offset, skipcrop, numThreads); + if(wavelet_decomp[lvltot]->memoryAllocationFailed) + memoryAllocationFailed = true; + } + coeff0 = buffer[bufferindex^1]; delete[] buffer[bufferindex]; } template - void wavelet_decomposition::reconstruct(E * dst) { - if(memoryAllocationFailed) + void wavelet_decomposition::reconstruct(E * dst, const float blend) { + + if(memoryAllocationFailed) return; - // data structure is wavcoeffs[scale][channel={lo,hi1,hi2,hi3}][pixel_array] - int m_w = 0; - int m_h2 = 0; - - for(int lvl=0;lvlm_w) - m_w = wavelet_decomp[lvl]->m_w; - if(m_h2 < wavelet_decomp[lvl]->m_h2) - m_h2 = wavelet_decomp[lvl]->m_h2; - } - E *tmpLo = new (std::nothrow) E[m_w*m_h2]; - if(tmpLo == NULL) { - memoryAllocationFailed = true; - return; - } + // data structure is wavcoeffs[scale][channel={lo,hi1,hi2,hi3}][pixel_array] - E *tmpHi = new (std::nothrow) E[m_w*m_h2]; - if(tmpHi == NULL) { - memoryAllocationFailed = true; - delete[] tmpLo; - return; - } - - for (int lvl=lvltot; lvl>0; lvl--) { - wavelet_decomp[lvl]->reconstruct_level(tmpLo, tmpHi, coeff0, coeff0, wavfilt_synth, wavfilt_synth, wavfilt_len, wavfilt_offset); + if(lvltot >= 1) { + int width = wavelet_decomp[1]->m_w; + int height = wavelet_decomp[1]->m_h; + + E *tmpHi = new (std::nothrow) E[width*height]; + if(tmpHi == NULL) { + memoryAllocationFailed = true; + return; + } + + for (int lvl=lvltot; lvl>0; lvl--) { + E *tmpLo = wavelet_decomp[lvl]->wavcoeffs[2]; // we can use this as buffer + wavelet_decomp[lvl]->reconstruct_level(tmpLo, tmpHi, coeff0, coeff0, wavfilt_synth, wavfilt_synth, wavfilt_len, wavfilt_offset); + delete wavelet_decomp[lvl]; + wavelet_decomp[lvl] = NULL; + } + delete[] tmpHi; } - wavelet_decomp[0]->reconstruct_level(tmpLo, tmpHi, coeff0, dst, wavfilt_synth, wavfilt_synth, wavfilt_len, wavfilt_offset); - delete[] coeff0; - coeff0 = NULL; - delete[] tmpLo; + int width = wavelet_decomp[0]->m_w; + int height = wavelet_decomp[0]->m_h2; + E *tmpLo; + if(wavelet_decomp[0]->bigBlockOfMemoryUsed()) // bigBlockOfMemoryUsed means that wavcoeffs[2] points to a block of memory big enough to hold the data + tmpLo = wavelet_decomp[0]->wavcoeffs[2]; + else { // allocate new block of memory + tmpLo = new (std::nothrow) E[width*height]; + if(tmpLo == NULL) { + memoryAllocationFailed = true; + return; + } + } + E *tmpHi = new (std::nothrow) E[width*height]; + if(tmpHi == NULL) { + memoryAllocationFailed = true; + if(!wavelet_decomp[0]->bigBlockOfMemoryUsed()) + delete[] tmpLo; + return; + } + + + wavelet_decomp[0]->reconstruct_level(tmpLo, tmpHi, coeff0, dst, wavfilt_synth, wavfilt_synth, wavfilt_len, wavfilt_offset, blend); + if(!wavelet_decomp[0]->bigBlockOfMemoryUsed()) + delete[] tmpLo; delete[] tmpHi; + delete wavelet_decomp[0]; + wavelet_decomp[0] = NULL; + delete[] coeff0; + coeff0 = NULL; } }; diff --git a/rtengine/cplx_wavelet_filter_coeffs.h b/rtengine/cplx_wavelet_filter_coeffs.h index 8f2bcbc49..c83a882be 100644 --- a/rtengine/cplx_wavelet_filter_coeffs.h +++ b/rtengine/cplx_wavelet_filter_coeffs.h @@ -20,11 +20,14 @@ namespace rtengine { -const int Daub4_len=6; const int Daub4_offset=2; -const float Daub4_anal[2][6] ALIGNED16 = {//analysis filter - {0, 0, 0.34150635, 0.59150635, 0.15849365, -0.091506351}, - {-0.091506351, -0.15849365, 0.59150635, -0.34150635, 0, 0}}; +const float Daub4_anal[2][6] ALIGNED16 = {//analysis filter + {0.f, 0.f, 0.34150635f, 0.59150635f, 0.15849365f, -0.091506351f}, + {-0.091506351f, -0.15849365f, 0.59150635f, -0.34150635f, 0.f, 0.f}}; + +const float Daub4_anal8[2][8] ALIGNED16 = {//analysis filter + {0.f,0.f, 0.235233605f, 0.57055846f, 0.3251825f, -0.09546721f, -0.060416105f, 0.02490875f}, + {-0.02490875f, -0.060416105f, 0.09546721f, 0.3251825f, -0.57055846f , 0.235233605f, 0.f, 0.f}}; }; diff --git a/rtengine/cplx_wavelet_level.h b/rtengine/cplx_wavelet_level.h index bf1d7727b..3eef39397 100644 --- a/rtengine/cplx_wavelet_level.h +++ b/rtengine/cplx_wavelet_level.h @@ -15,7 +15,7 @@ * along with RawTherapee. If not, see . * * 2010 Ilya Popov - * 2012 Emil Martinec + * 2012 Emil Martinec * 2014 Ingo Weyrich */ @@ -24,8 +24,8 @@ #include #include "rt_math.h" -#include "opthelper.h" -#include "stdio.h" +#include "opthelper.h" +#include "stdio.h" namespace rtengine { template @@ -36,14 +36,14 @@ namespace rtengine { int lvl; // whether to subsample the output - bool subsamp_out; - + bool subsamp_out; + int numThreads; // spacing of filter taps int skip; - - bool bigBlockOfMemory; + + bool bigBlockOfMemory; // allocation and destruction of data storage T ** create(int n); void destroy(T ** subbands); @@ -57,19 +57,19 @@ namespace rtengine { void AnalysisFilterSubsampHorizontal (T * srcbuffer, T * dstLo, T * dstHi, float *filterLo, float *filterHi, const int taps, const int offset, const int srcwidth, const int dstwidth, const int row); -#ifdef __SSE2__ - void AnalysisFilterSubsampVertical (T * srcbuffer, T * dstLo, T * dstHi, float (*filterLo)[4], float (*filterHi)[4], - const int taps, const int offset, const int width, const int height, const int row); -#else - void AnalysisFilterSubsampVertical (T * srcbuffer, T * dstLo, T * dstHi, float *filterLo, float *filterHi, - int const taps, const int offset, const int width, const int height, const int row); -#endif - void SynthesisFilterSubsampHorizontal (T * srcLo, T * srcHi, T * dst, - float *filterLo, float *filterHi, const int taps, const int offset, const int scrwidth, const int dstwidth, const int height); #ifdef __SSE2__ - void SynthesisFilterSubsampVertical (T * srcLo, T * srcHi, T * dst, float (*filterLo)[4], float (*filterHi)[4], const int taps, const int offset, const int width, const int srcheight, const int dstheight); -#else - void SynthesisFilterSubsampVertical (T * srcLo, T * srcHi, T * dst, float *filterLo, float *filterHi, const int taps, const int offset, const int width, const int srcheight, const int dstheight); + void AnalysisFilterSubsampVertical (T * srcbuffer, T * dstLo, T * dstHi, float (*filterLo)[4], float (*filterHi)[4], + const int taps, const int offset, const int width, const int height, const int row); +#else + void AnalysisFilterSubsampVertical (T * srcbuffer, T * dstLo, T * dstHi, float *filterLo, float *filterHi, + int const taps, const int offset, const int width, const int height, const int row); +#endif + void SynthesisFilterSubsampHorizontal (T * srcLo, T * srcHi, T * dst, + float *filterLo, float *filterHi, const int taps, const int offset, const int scrwidth, const int dstwidth, const int height); +#ifdef __SSE2__ + void SynthesisFilterSubsampVertical (T * srcLo, T * srcHi, T * dst, float (*filterLo)[4], float (*filterHi)[4], const int taps, const int offset, const int width, const int srcheight, const int dstheight, const float blend); +#else + void SynthesisFilterSubsampVertical (T * srcLo, T * srcHi, T * dst, float *filterLo, float *filterHi, const int taps, const int offset, const int width, const int srcheight, const int dstheight, const float blend); #endif public: bool memoryAllocationFailed; @@ -89,88 +89,86 @@ namespace rtengine { skip = 1; for (int n=0; n>n)&1); - } - skip /= skipcrop; - if(skip < 1) skip=1; + } + skip /= skipcrop; + if(skip < 1) skip=1; } m_w2 = (subsamp_out ? (w+1)/2 : w); m_h2 = (subsamp_out ? (h+1)/2 : h); - wavcoeffs = create((m_w2)*(m_h2)); + wavcoeffs = create((m_w2)*(m_h2)); if(!memoryAllocationFailed) decompose_level(src, dst, filterV, filterH, len, offset); } - ~wavelet_level() - { + ~wavelet_level() { destroy(wavcoeffs); } - T ** subbands() const - { + T ** subbands() const { return wavcoeffs; } - T * lopass() const - { + T * lopass() const { return wavcoeffs[0]; } - int width() const - { + int width() const { return m_w2; } - int height() const - { + int height() const { return m_h2; } - int stride() const - { + int stride() const { return skip; } + + bool bigBlockOfMemoryUsed() const { + return bigBlockOfMemory; + } template void decompose_level(E *src, E *dst, float *filterV, float *filterH, int len, int offset); template - void reconstruct_level(E* tmpLo, E* tmpHi, E *src, E *dst, float *filterV, float *filterH, int taps, int offset); + void reconstruct_level(E* tmpLo, E* tmpHi, E *src, E *dst, float *filterV, float *filterH, int taps, int offset, const float blend = 1.f); }; template T ** wavelet_level::create(int n) { - T * data = new (std::nothrow) T[3*n]; - if(data == NULL) { - bigBlockOfMemory = false; + T * data = new (std::nothrow) T[3*n]; + if(data == NULL) { + bigBlockOfMemory = false; } T ** subbands = new T*[4]; - for(int j = 1; j < 4; j++) { + for(int j = 1; j < 4; j++) { if(bigBlockOfMemory) - subbands[j] = data + n * (j-1); - else { - subbands[j] = new (std::nothrow) T[n]; - if(subbands[j] == NULL) { - printf("Couldn't allocate memory in level %d of wavelet\n",lvl); - memoryAllocationFailed = true; - } - } + subbands[j] = data + n * (j-1); + else { + subbands[j] = new (std::nothrow) T[n]; + if(subbands[j] == NULL) { + printf("Couldn't allocate memory in level %d of wavelet\n",lvl); + memoryAllocationFailed = true; + } + } } return subbands; } template void wavelet_level::destroy(T ** subbands) { - if(subbands) { + if(subbands) { if(bigBlockOfMemory) - delete[] subbands[1]; - else { - for(int j = 1; j < 4; j++) { - if(subbands[j] != NULL) - delete[] subbands[j]; - } + delete[] subbands[1]; + else { + for(int j = 1; j < 4; j++) { + if(subbands[j] != NULL) + delete[] subbands[j]; + } } delete[] subbands; } @@ -180,7 +178,7 @@ namespace rtengine { void wavelet_level::AnalysisFilterHaarHorizontal (const T * const RESTRICT srcbuffer, T * RESTRICT dstLo, T * RESTRICT dstHi, const int width, const int row) { /* Basic convolution code * Applies a Haar filter - */ + */ for(int i = 0; i < (width - skip); i++) { dstLo[row*width+i] = (srcbuffer[i] + srcbuffer[i+skip]); dstHi[row*width+i] = (srcbuffer[i] - srcbuffer[i+skip]); @@ -190,22 +188,22 @@ namespace rtengine { dstHi[row*width+i] = (srcbuffer[i] - srcbuffer[i-skip]); } } - + template void wavelet_level::AnalysisFilterHaarVertical (const T * const RESTRICT srcbuffer, T * RESTRICT dstLo, T * RESTRICT dstHi, const int width, const int height, const int row) { /* Basic convolution code * Applies a Haar filter - */ - if(row < (height - skip)) { - for(int j=0;j=max(height-skip,skip)) { - for(int j=0;j1) -#endif +#endif for (int k=0; k void wavelet_level::SynthesisFilterHaarVertical (const T * const RESTRICT srcLo, const T * const RESTRICT srcHi, T * RESTRICT dst, const int width, const int height) { /* Basic convolution code * Applies a Haar filter * */ -#ifdef _OPENMP -#pragma omp parallel num_threads(numThreads) if(numThreads>1) -#endif -{ -#ifdef _OPENMP -#pragma omp for nowait -#endif +#ifdef _OPENMP +#pragma omp parallel num_threads(numThreads) if(numThreads>1) +#endif +{ +#ifdef _OPENMP +#pragma omp for nowait +#endif for(int i = 0; i < skip; i++) { - for(int j=0;j void wavelet_level::AnalysisFilterSubsampHorizontal (T * RESTRICT srcbuffer, T * RESTRICT dstLo, T * RESTRICT dstHi, float * RESTRICT filterLo, float *RESTRICT filterHi, const int taps, const int offset, const int srcwidth, const int dstwidth, const int row) { @@ -266,16 +264,16 @@ namespace rtengine { * the input pixel, and skipping 'skip' pixels between taps * Output is subsampled by two */ - // calculate coefficients + // calculate coefficients for(int i = 0; i < srcwidth; i+=2) { float lo = 0.f, hi = 0.f; if (LIKELY(i>skip*taps && i void wavelet_level::AnalysisFilterSubsampVertical (T * RESTRICT srcbuffer, T * RESTRICT dstLo, T * RESTRICT dstHi, float (* RESTRICT filterLo)[4], float (* RESTRICT filterHi)[4], - const int taps, const int offset, const int width, const int height, const int row) { + +#ifdef __SSE2__ + template SSEFUNCTION void wavelet_level::AnalysisFilterSubsampVertical (T * RESTRICT srcbuffer, T * RESTRICT dstLo, T * RESTRICT dstHi, float (* RESTRICT filterLo)[4], float (* RESTRICT filterHi)[4], + const int taps, const int offset, const int width, const int height, const int row) { /* Basic convolution code * Applies an FIR filter 'filter' with filter length 'taps', @@ -298,17 +296,17 @@ namespace rtengine { * Output is subsampled by two */ - // calculate coefficients - if (LIKELY(row>skip*taps && rowskip*taps && row void wavelet_level::AnalysisFilterSubsampVertical (T * RESTRICT srcbuffer, T * RESTRICT dstLo, T * RESTRICT dstHi, float * RESTRICT filterLo, float * RESTRICT filterHi, - const int taps, const int offset, const int width, const int height, const int row) { + const int taps, const int offset, const int width, const int height, const int row) { /* Basic convolution code * Applies an FIR filter 'filter' with filter length 'taps', @@ -358,14 +356,14 @@ namespace rtengine { * Output is subsampled by two */ - // calculate coefficients + // calculate coefficients if (LIKELY(row>skip*taps && row void wavelet_level::SynthesisFilterSubsampHorizontal (T * RESTRICT srcLo, T * RESTRICT srcHi, T * RESTRICT dst, float * RESTRICT filterLo, float * RESTRICT filterHi, const int taps, const int offset, const int srcwidth, const int dstwidth, const int height) { /* Basic convolution code @@ -393,13 +391,13 @@ namespace rtengine { * the input pixel, and skipping 'skip' pixels between taps * Output is subsampled by two */ - + // calculate coefficients - int shift = skip*(taps-offset-1);//align filter with data -#ifdef _OPENMP -#pragma omp parallel for num_threads(numThreads) if(numThreads>1) -#endif - for (int k=0; k1) +#endif + for (int k=0; k SSEFUNCTION void wavelet_level::SynthesisFilterSubsampVertical (T * RESTRICT srcLo, T * RESTRICT srcHi, T * RESTRICT dst, float (* RESTRICT filterLo)[4], float (* RESTRICT filterHi)[4], const int taps, const int offset, const int width, const int srcheight, const int dstheight) + template SSEFUNCTION void wavelet_level::SynthesisFilterSubsampVertical (T * RESTRICT srcLo, T * RESTRICT srcHi, T * RESTRICT dst, float (* RESTRICT filterLo)[4], float (* RESTRICT filterHi)[4], const int taps, const int offset, const int width, const int srcheight, const int dstheight, const float blend) { /* Basic convolution code @@ -446,34 +444,36 @@ namespace rtengine { * the input pixel, and skipping 'skip' pixels between taps * Output is subsampled by two */ - + const float srcFactor = 1.f - blend; // calculate coefficients - int shift=skip*(taps-offset-1);//align filter with data - __m128 fourv = _mm_set1_ps(4.f); -#ifdef _OPENMP + int shift=skip*(taps-offset-1);//align filter with data + __m128 fourv = _mm_set1_ps(4.f); + __m128 srcFactorv = _mm_set1_ps(srcFactor); + __m128 dstFactorv = _mm_set1_ps(blend); +#ifdef _OPENMP #pragma omp parallel for num_threads(numThreads) if(numThreads>1) -#endif +#endif for(int i = 0; i < dstheight; i++) { int i_src = (i+shift)/2; int begin = (i+shift)%2; //TODO: this is correct only if skip=1; otherwise, want to work with cosets of length 'skip' - if (LIKELY(i>skip*taps && i<(dstheight-skip*taps))) {//bulk + if (LIKELY(i>skip*taps && i<(dstheight-skip*taps))) {//bulk int k; - for (k=0; k void wavelet_level::SynthesisFilterSubsampVertical (T * RESTRICT srcLo, T * RESTRICT srcHi, T * RESTRICT dst, float * RESTRICT filterLo, float * RESTRICT filterHi, const int taps, const int offset, const int width, const int srcheight, const int dstheight) +#else + template void wavelet_level::SynthesisFilterSubsampVertical (T * RESTRICT srcLo, T * RESTRICT srcHi, T * RESTRICT dst, float * RESTRICT filterLo, float * RESTRICT filterHi, const int taps, const int offset, const int width, const int srcheight, const int dstheight, const float blend) { /* Basic convolution code @@ -504,13 +504,14 @@ namespace rtengine { * the input pixel, and skipping 'skip' pixels between taps * Output is subsampled by two */ - + + const float srcFactor = 1.f - blend; // calculate coefficients - int shift=skip*(taps-offset-1);//align filter with data - -#ifdef _OPENMP + int shift=skip*(taps-offset-1);//align filter with data + +#ifdef _OPENMP #pragma omp parallel for num_threads(numThreads) if(numThreads>1) -#endif +#endif for(int i = 0; i < dstheight; i++) { int i_src = (i+shift)/2; int begin = (i+shift)%2; @@ -520,9 +521,9 @@ namespace rtengine { float tot = 0.f; for (int j=begin, l=0; j template SSEFUNCTION void wavelet_level::decompose_level(E *src, E *dst, float *filterV, float *filterH, int taps, int offset) { - /* filter along rows and columns */ + /* filter along rows and columns */ float filterVarray[2*taps][4] ALIGNED64; - if(subsamp_out) { - for(int i=0;i<2*taps;i++) { - for(int j=0;j<4;j++) { - filterVarray[i][j] = filterV[i]; - } - } - } -#ifdef _OPENMP -#pragma omp parallel num_threads(numThreads) if(numThreads>1) -#endif -{ - T tmpLo[m_w] ALIGNED64; - T tmpHi[m_w] ALIGNED64; - if(subsamp_out) { -#ifdef _OPENMP -#pragma omp for -#endif - for(int row=0;row1) +#endif +{ + T tmpLo[m_w] ALIGNED64; + T tmpHi[m_w] ALIGNED64; + if(subsamp_out) { +#ifdef _OPENMP +#pragma omp for +#endif + for(int row=0;row template void wavelet_level::decompose_level(E *src, E *dst, float *filterV, float *filterH, int taps, int offset) { -#ifdef _OPENMP -#pragma omp parallel num_threads(numThreads) if(numThreads>1) -#endif -{ - T tmpLo[m_w] ALIGNED64; - T tmpHi[m_w] ALIGNED64; +#ifdef _OPENMP +#pragma omp parallel num_threads(numThreads) if(numThreads>1) +#endif +{ + T tmpLo[m_w] ALIGNED64; + T tmpHi[m_w] ALIGNED64; /* filter along rows and columns */ - if(subsamp_out) { -#ifdef _OPENMP -#pragma omp for -#endif - for(int row=0;row template SSEFUNCTION void wavelet_level::reconstruct_level(E* tmpLo, E* tmpHi, E * src, E *dst, float *filterV, float *filterH, int taps, int offset) { - if(memoryAllocationFailed) - return; - - /* filter along rows and columns */ - if (subsamp_out) { - float filterVarray[2*taps][4] ALIGNED64; - for(int i=0;i<2*taps;i++) { - for(int j=0;j<4;j++) { - filterVarray[i][j] = filterV[i]; - } - } - SynthesisFilterSubsampHorizontal (src, wavcoeffs[1], tmpLo, filterH, filterH+taps, taps, offset, m_w2, m_w, m_h2); - SynthesisFilterSubsampHorizontal (wavcoeffs[2], wavcoeffs[3], tmpHi, filterH, filterH+taps, taps, offset, m_w2, m_w, m_h2); - SynthesisFilterSubsampVertical (tmpLo, tmpHi, dst, filterVarray, filterVarray+taps, taps, offset, m_w, m_h2, m_h); - } else { - SynthesisFilterHaarHorizontal (src, wavcoeffs[1], tmpLo, m_w, m_h2); - SynthesisFilterHaarHorizontal (wavcoeffs[2], wavcoeffs[3], tmpHi, m_w, m_h2); - SynthesisFilterHaarVertical (tmpLo, tmpHi, dst, m_w, m_h); - } - } -#else - template template void wavelet_level::reconstruct_level(E* tmpLo, E* tmpHi, E * src, E *dst, float *filterV, float *filterH, int taps, int offset) { - if(memoryAllocationFailed) - return; + +#ifdef __SSE2__ + + template template SSEFUNCTION void wavelet_level::reconstruct_level(E* tmpLo, E* tmpHi, E * src, E *dst, float *filterV, float *filterH, int taps, int offset, const float blend) { + if(memoryAllocationFailed) + return; + /* filter along rows and columns */ if (subsamp_out) { - SynthesisFilterSubsampHorizontal (src, wavcoeffs[1], tmpLo, filterH, filterH+taps, taps, offset, m_w2, m_w, m_h2); + float filterVarray[2*taps][4] ALIGNED64; + for(int i=0;i<2*taps;i++) { + for(int j=0;j<4;j++) { + filterVarray[i][j] = filterV[i]; + } + } SynthesisFilterSubsampHorizontal (wavcoeffs[2], wavcoeffs[3], tmpHi, filterH, filterH+taps, taps, offset, m_w2, m_w, m_h2); - SynthesisFilterSubsampVertical (tmpLo, tmpHi, dst, filterV, filterV+taps, taps, offset, m_w, m_h2, m_h); - } else { - SynthesisFilterHaarHorizontal (src, wavcoeffs[1], tmpLo, m_w, m_h2); + SynthesisFilterSubsampHorizontal (src, wavcoeffs[1], tmpLo, filterH, filterH+taps, taps, offset, m_w2, m_w, m_h2); + SynthesisFilterSubsampVertical (tmpLo, tmpHi, dst, filterVarray, filterVarray+taps, taps, offset, m_w, m_h2, m_h, blend); + } else { SynthesisFilterHaarHorizontal (wavcoeffs[2], wavcoeffs[3], tmpHi, m_w, m_h2); - SynthesisFilterHaarVertical (tmpLo, tmpHi, dst, m_w, m_h); + SynthesisFilterHaarHorizontal (src, wavcoeffs[1], tmpLo, m_w, m_h2); + SynthesisFilterHaarVertical (tmpLo, tmpHi, dst, m_w, m_h); + } + } +#else + template template void wavelet_level::reconstruct_level(E* tmpLo, E* tmpHi, E * src, E *dst, float *filterV, float *filterH, int taps, int offset, const float blend) { + if(memoryAllocationFailed) + return; + /* filter along rows and columns */ + if (subsamp_out) { + SynthesisFilterSubsampHorizontal (wavcoeffs[2], wavcoeffs[3], tmpHi, filterH, filterH+taps, taps, offset, m_w2, m_w, m_h2); + SynthesisFilterSubsampHorizontal (src, wavcoeffs[1], tmpLo, filterH, filterH+taps, taps, offset, m_w2, m_w, m_h2); + SynthesisFilterSubsampVertical (tmpLo, tmpHi, dst, filterV, filterV+taps, taps, offset, m_w, m_h2, m_h, blend); + } else { + SynthesisFilterHaarHorizontal (wavcoeffs[2], wavcoeffs[3], tmpHi, m_w, m_h2); + SynthesisFilterHaarHorizontal (src, wavcoeffs[1], tmpLo, m_w, m_h2); + SynthesisFilterHaarVertical (tmpLo, tmpHi, dst, m_w, m_h); } } #endif diff --git a/rtengine/dcrop.cc b/rtengine/dcrop.cc index 39e3f1759..38606a86c 100644 --- a/rtengine/dcrop.cc +++ b/rtengine/dcrop.cc @@ -258,13 +258,13 @@ void Crop::update (int todo) { int W = origCrop->getWidth(); int H = origCrop->getHeight(); Imagefloat *provicalc = new Imagefloat ((W+1)/2, (H+1)/2);//for denoise curves - for(int ii=0;iir(ii>>1,jj>>1) = origCrop->r(ii,jj); provicalc->g(ii>>1,jj>>1) = origCrop->g(ii,jj); provicalc->b(ii>>1,jj>>1) = origCrop->b(ii,jj); } - } + } parent->imgsrc->convertColorSpace(provicalc, params.icm, parent->currWB, params.raw);//for denoise luminance curve float maxr=0.f; @@ -352,13 +352,13 @@ void Crop::update (int todo) { parent->imgsrc->getImage (parent->currWB, tr, origCropPart, ppP, params.toneCurve, params.icm, params.raw ); // we only need image reduced to 1/4 here - for(int ii=0;iir(ii>>1,jj>>1) = origCropPart->r(ii,jj); provicalc->g(ii>>1,jj>>1) = origCropPart->g(ii,jj); provicalc->b(ii>>1,jj>>1) = origCropPart->b(ii,jj); } - } + } parent->imgsrc->convertColorSpace(provicalc, params.icm, parent->currWB, params.raw);//for denoise luminance curve float pondcorrec=1.0f; @@ -497,13 +497,13 @@ void Crop::update (int todo) { int W = origCrop->getWidth(); int H = origCrop->getHeight(); calclum = new Imagefloat ((W+1)/2, (H+1)/2);//for denoise curves - for(int ii=0;iir(ii>>1,jj>>1) = origCrop->r(ii,jj); calclum->g(ii>>1,jj>>1) = origCrop->g(ii,jj); calclum->b(ii>>1,jj>>1) = origCrop->b(ii,jj); } - } + } parent->imgsrc->convertColorSpace(calclum, params.icm, parent->currWB, params.raw);//for denoise luminance curve } @@ -688,11 +688,16 @@ void Crop::update (int todo) { if(minwin*skip < 256) maxlevelcrop = 7;//sampling 128 if(minwin*skip < 128) maxlevelcrop = 6; if(minwin < 64) maxlevelcrop = 5; + + int realtile; + if(params.wavelet.Tilesmethod=="big") realtile=22; + if(params.wavelet.Tilesmethod=="lit") realtile=12; + int tilesize; int overlap; tilesize = 1024; overlap = 128; - tilesize=128*params.wavelet.tiles; + tilesize=128*realtile; //overlap=(int) tilesize*params->wavelet.overl; overlap=(int) tilesize*0.125f; // printf("overl=%d\n",overlap); diff --git a/rtengine/improcfun.h b/rtengine/improcfun.h index 8143ed255..f2fc34bc5 100644 --- a/rtengine/improcfun.h +++ b/rtengine/improcfun.h @@ -287,11 +287,11 @@ class ImProcFunctions { void Tile_calc (int tilesize, int overlap, int kall, int imwidth, int imheight, int &numtiles_W, int &numtiles_H, int &tilewidth, int &tileheight, int &tileWskip, int &tileHskip); void ip_wavelet(LabImage * lab, LabImage * dst, int kall, const procparams::WaveletParams & waparams, const WavCurve & wavCLVCcurve, const WavOpacityCurveRG & waOpacityCurveRG, const WavOpacityCurveBY & waOpacityCurveBY, int skip); void WaveletcontAllL(LabImage * lab, float **varhue, float **varchrom, wavelet_decomposition &WaveletCoeffs_L, - struct cont_params cp); + struct cont_params cp, int skip); void WaveletcontAllAB(LabImage * lab, float **varhue, float **varchrom, wavelet_decomposition &WaveletCoeffs_a, struct cont_params cp, const bool useChannelA); void ContAllL (LabImage * lab, float **varhue, float **varchrom, float ** WavCoeffs_L, float * WavCoeffs_L0, int level, int dir, struct cont_params cp, - int W_L, int H_L); + int W_L, int H_L, int skip); void ContAllAB (LabImage * lab, float **varhue, float **varchrom, float ** WavCoeffs_a, float * WavCoeffs_a0, int level, int dir, struct cont_params cp, int W_ab, int H_ab, const bool useChannelA); void Evaluate(wavelet_decomposition &WaveletCoeffs_L, wavelet_decomposition &WaveletCoeffs_a, diff --git a/rtengine/ipwavelet.cc b/rtengine/ipwavelet.cc index 1bf444d9b..0687c98a7 100644 --- a/rtengine/ipwavelet.cc +++ b/rtengine/ipwavelet.cc @@ -73,7 +73,7 @@ struct cont_params { float mul[10]; int chrom; int chro; - int unif; + int contrast; float th; float thH; float conres; @@ -87,7 +87,9 @@ struct cont_params { float b_lpast,t_lpast,b_rpast,t_rpast; float b_lsat,t_lsat,b_rsat,t_rsat; - + int rad; + int val; + int til; int numlevH, numlevS; float mulC[9]; float mulopaRG[9]; @@ -98,15 +100,16 @@ struct cont_params { int CHmet; bool HSmet; bool avoi; + float strength; }; int wavNestedLevels = 1; - void ImProcFunctions::ip_wavelet(LabImage * lab, LabImage * dst, int kall, const procparams::WaveletParams & waparams, const WavCurve & wavCLVCcurve, const WavOpacityCurveRG & waOpacityCurveRG, const WavOpacityCurveBY & waOpacityCurveBY, int skip) - { - MyTime t1e,t2e; - t1e.set(); - +SSEFUNCTION void ImProcFunctions::ip_wavelet(LabImage * lab, LabImage * dst, int kall, const procparams::WaveletParams & waparams, const WavCurve & wavCLVCcurve, const WavOpacityCurveRG & waOpacityCurveRG, const WavOpacityCurveBY & waOpacityCurveBY, int skip) +{ + MyTime t1e,t2e; + t1e.set(); + #ifdef _DEBUG // init variables to display Munsell corrections MunsellDebugInfo* MunsDebugInfo = new MunsellDebugInfo(); @@ -119,11 +122,18 @@ int wavNestedLevels = 1; }; const short int imheight=lab->H, imwidth=lab->W; struct cont_params cp; - cp.avoi=false; - if(params->wavelet.avoid) cp.avoi=true; - + cp.avoi = params->wavelet.avoid; + int N=imheight*imwidth; int maxmul=params->wavelet.thres; + static const float scales[10] = {1.f,2.f,4.f,8.f,16.f,32.f,64.f,128.f,256.f,512.f}; + float scaleskip[10]; + for(int sc=0;sc<10;sc++) + scaleskip[sc]=scales[sc]/skip; + float atten0 = 0.40f; + float atten123=0.90f; + + int DaubLen = settings->daubech ? 8 : 6; cp.curv=false; cp.opaRG=false; cp.opaBY=false; @@ -133,6 +143,9 @@ int wavNestedLevels = 1; if(params->wavelet.CHmethod=="link") cp.CHmet=2; if(params->wavelet.HSmethod=="with") cp.HSmet=true; + //printf("params->wavelet.strength : %d\n",params->wavelet.strength); + cp.strength = min(1.f,max(0.f,((float)params->wavelet.strength / 100.f))); + //printf("cp.strength : %f\n",cp.strength); if(wavCLVCcurve) cp.curv=true; if(cp.curv) {//convert curve in discret values @@ -189,9 +202,24 @@ int wavNestedLevels = 1; cp.mul[m]=waparams.c[m]; cp.mul[9]=(float) waparams.sup; + for(int sc=0;sc<10;sc++) {//reduce strength if zoom < 100% for contrast + if(sc==0) {if(scaleskip[sc] < 1.f) cp.mul[sc]*=(atten0*scaleskip[sc]);} + else {if(scaleskip[sc] < 1.f) cp.mul[sc]*=(atten123*scaleskip[sc]);} + } + + if(settings->verbose) printf("Wav mul 0=%f 1=%f 2=%f 3=%f 4=%f 5=%f 6=%f 7=%f 8=%f 9=%f\n",cp.mul[0],cp.mul[1],cp.mul[2],cp.mul[3],cp.mul[4],cp.mul[5],cp.mul[6],cp.mul[7],cp.mul[8],cp.mul[9]); + for(int sc=0;sc<9;sc++) {//reduce strength if zoom < 100% for chroma and tuning + if(sc==0) {if(scaleskip[sc] < 1.f) {cp.mulC[sc]*=(atten0*scaleskip[sc]);cp.mulopaRG[sc]*=(atten0*scaleskip[sc]);cp.mulopaBY[sc]*=(atten0*scaleskip[sc]);}} + else {if(scaleskip[sc] < 1.f) {cp.mulC[sc]*=(atten123*scaleskip[sc]);cp.mulopaRG[sc]*=(atten123*scaleskip[sc]);cp.mulopaBY[sc]*=(atten123*scaleskip[sc]);}} + } + cp.chro=waparams.chro; cp.chrom=waparams.chroma; - cp.unif=waparams.unif; + cp.contrast=waparams.contrast; + cp.rad=waparams.edgrad; + cp.val=waparams.edgval; + cp.til=waparams.edgthresh; + cp.conres=waparams.rescon; cp.conresH=waparams.resconH; cp.chrores=waparams.reschro; @@ -340,8 +368,10 @@ int wavNestedLevels = 1; #endif +#ifdef _OPENMP #pragma omp parallel num_threads(numthreads) - { +#endif +{ float *mean = new float [9]; float *meanN = new float [9]; float *sigma = new float [9]; @@ -364,10 +394,22 @@ int wavNestedLevels = 1; int width = tileright-tileleft; int height = tilebottom-tiletop; LabImage * labco; - if(numtiles == 1 && !cp.avoi) // untiled processing and no 'Avoid Colour Shift' => we can use output buffer for labco + float **Lold; + float *LoldBuffer = NULL; + if(numtiles == 1) { // untiled processing => we can use output buffer for labco labco = dst; - else + if(cp.avoi) { // we need a buffer to hold a copy of the L channel + Lold = new float*[tileheight]; + LoldBuffer = new float[tilewidth*tileheight]; + memcpy(LoldBuffer, lab->L[0], tilewidth*tileheight*sizeof(float)); + for (int i=0; iL; + } #ifdef _OPENMP #pragma omp parallel for num_threads(wavNestedLevels) if(wavNestedLevels>1) @@ -375,82 +417,149 @@ int wavNestedLevels = 1; for (int i=tiletop; ia[i][j]); + bv = LVFU(lab->b[i][j]); + huev = xatan2f(bv,av); + chrov = _mm_sqrt_ps(SQRV(av)+SQRV(bv)) / c327d68v; + _mm_storeu_ps(&varhue[i1][j1],huev); + _mm_storeu_ps(&varchro[i1][j1], chrov); + if(labco != lab) { + _mm_storeu_ps(&(labco->L[i1][j1]),LVFU(lab->L[i][j])); + _mm_storeu_ps(&(labco->a[i1][j1]),av); + _mm_storeu_ps(&(labco->b[i1][j1]),bv); + } + } +#else + j=tileleft; +#endif + for (; jL[i][j]; float a=lab->a[i][j]; float b=lab->b[i][j]; - labco->L[i1][j1] = L; - labco->a[i1][j1] = a; - labco->b[i1][j1] = b; varhue[i1][j1]=xatan2f(b,a); - varchro[i1][j1]=(sqrt(a*a+b*b))/327.68f; + varchro[i1][j1]=(sqrtf(a*a+b*b))/327.68f; + if(labco != lab) { + labco->L[i1][j1] = lab->L[i][j]; + labco->a[i1][j1] = a; + labco->b[i1][j1] = b; + } } } //to avoid artifacts in blue sky - if(params->wavelet.median) { - float** tmL; - int wid=labco->W; - int hei=labco->H; - int borderL = 1; - tmL = new float*[hei]; - for (int i=0; iL[i][j]; + if(params->wavelet.median) { + float** tmL; + int wid=labco->W; + int hei=labco->H; + int borderL = 1; + tmL = new float*[hei]; + for (int i=0; iL[i][j]; + } } - } - + #ifdef _OPENMP #pragma omp parallel for num_threads(wavNestedLevels) if(wavNestedLevels>1) #endif - for (int i=1; i - 2.6f) && (varchro[i][j] > 15.f && varchro[i][j] < 55.f) && labco->L[i][j] > 5000.f) //blue sky + med3x3 ==> after for more effect use denoise - med3(labco->L[i][j] ,labco->L[i-1][j], labco->L[i+1][j] ,labco->L[i][j+1],labco->L[i][j-1], labco->L[i-1][j-1],labco->L[i-1][j+1],labco->L[i+1][j-1],labco->L[i+1][j+1],tmL[i][j]);//3x3 - } - } - for(int i = borderL; i < hei-borderL; i++ ) { - for(int j = borderL; j < wid-borderL; j++) { - labco->L[i][j] = tmL[i][j]; + for (int i=1; i - 2.5f) && (varchro[i][j] > 15.f && varchro[i][j] < 55.f) && labco->L[i][j] > 6000.f) //blue sky + med3x3 ==> after for more effect use denoise + med3(labco->L[i][j] ,labco->L[i-1][j], labco->L[i+1][j] ,labco->L[i][j+1],labco->L[i][j-1], labco->L[i-1][j-1],labco->L[i-1][j+1],labco->L[i+1][j-1],labco->L[i+1][j+1],tmL[i][j]);//3x3 + } } + for(int i = borderL; i < hei-borderL; i++ ) { + for(int j = borderL; j < wid-borderL; j++) { + labco->L[i][j] = tmL[i][j]; + } + } + + for (int i=0; iwavelet.skinprotect != 0.0 || (cp.curv && cp.CHmet!=2)) // reduce the arrays to get faster access in following processing - for (int i=0; i<(tileheight)/2; i++) { - for (int j=0; j<(tilewidth)/2; j++) { + if(numtiles == 1) { + // reduce the varhue array to get faster access in following processing and reduce peak memory usage + float temphue[(tilewidth+1)/2] ALIGNED64; + for (int i=0; i<(tileheight+1)/2; i++) { + for (int j=0; j<(tilewidth+1)/2; j++) { + temphue[j]=varhue[i*2][j*2]; + } + delete [] varhue[i]; + varhue[i] = new float[(tilewidth+1)/2]; + memcpy(varhue[i],temphue, ((tilewidth+1)/2) * sizeof(float)); + } + for(int i=(tileheight+1)/2;iW * labco->H; - wavelet_decomposition* Ldecomp = new wavelet_decomposition (labco->data, labco->W, labco->H, levwav, 1, skip, max(1,wavNestedLevels) ); - if(!Ldecomp->memoryAllocationFailed) { - WaveletcontAllL(labco, varhue, varchro, *Ldecomp, cp); - Ldecomp->reconstruct(labco->data); - } - delete Ldecomp; - - wavelet_decomposition* adecomp = new wavelet_decomposition (labco->data+datalen, labco->W, labco->H,levwav, 1, skip, max(1,wavNestedLevels) ); - if(!adecomp->memoryAllocationFailed) { - WaveletcontAllAB(labco, varhue, varchro, *adecomp, cp, true); - adecomp->reconstruct(labco->data+datalen); - } - delete adecomp; - - wavelet_decomposition* bdecomp = new wavelet_decomposition (labco->data+2*datalen, labco->W, labco->H, levwav, 1, skip, max(1,wavNestedLevels) ); - if(!bdecomp->memoryAllocationFailed) { - WaveletcontAllAB(labco, varhue, varchro, *bdecomp, cp, false); - bdecomp->reconstruct(labco->data+2*datalen); - } - delete bdecomp; + int levwavL = levwav; + //printf("LevwavL before: %d\n",levwavL); + if(cp.contrast == 0 && cp.conres == 0.f && cp.conresH == 0.f && cp.val ==0 && params->wavelet.CLmethod=="all") { // no processing of residual L or edge=> we probably can reduce the number of levels + while(levwavL > 0 && cp.mul[levwavL-1] == 0.f) // cp.mul[level] == 0.f means no changes to level + levwavL--; + } + //printf("LevwavL after: %d\n",levwavL); + if(levwavL > 0) { + wavelet_decomposition* Ldecomp = new wavelet_decomposition (labco->data, labco->W, labco->H, levwavL, 1, skip, max(1,wavNestedLevels), DaubLen ); + if(!Ldecomp->memoryAllocationFailed) { + WaveletcontAllL(labco, varhue, varchro, *Ldecomp, cp, skip); + Ldecomp->reconstruct(labco->data, cp.strength); + } + delete Ldecomp; + } + int levwava = levwav; + //printf("Levwava before: %d\n",levwava); + if(cp.chrores == 0.f && params->wavelet.CLmethod=="all") { // no processing of residual ab => we probably can reduce the number of levels + while(levwava > 0 && (((cp.CHmet==2 && (cp.chro == 0.f || cp.mul[levwava-1] == 0.f )) || (cp.CHmet!=2 && (levwava == 10 || (!cp.curv || (cp.curv && cp.mulC[levwava-1] == 0.f)))))) && (!cp.opaRG || levwava == 10 || (cp.opaRG && cp.mulopaRG[levwava-1] == 0.f))) { + levwava--; + } + } + //printf("Levwava after: %d\n",levwava); + if(levwava > 0) { + wavelet_decomposition* adecomp = new wavelet_decomposition (labco->data+datalen, labco->W, labco->H,levwava, 1, skip, max(1,wavNestedLevels), DaubLen ); + if(!adecomp->memoryAllocationFailed) { + WaveletcontAllAB(labco, varhue, varchro, *adecomp, cp, true); + adecomp->reconstruct(labco->data+datalen, cp.strength); + } + delete adecomp; + } + int levwavb = levwav; + //printf("Levwavb before: %d\n",levwavb); + if(cp.chrores == 0.f && params->wavelet.CLmethod=="all") { // no processing of residual ab => we probably can reduce the number of levels + while(levwavb > 0 && (((cp.CHmet==2 && (cp.chro == 0.f || cp.mul[levwavb-1] == 0.f )) || (cp.CHmet!=2 && (levwavb == 10 || (!cp.curv || (cp.curv && cp.mulC[levwavb-1] == 0.f)))))) && (!cp.opaBY || levwavb == 10 || (cp.opaBY && cp.mulopaBY[levwavb-1] == 0.f))) { + levwavb--; + } + } + //printf("Levwavb after: %d\n",levwavb); + if(levwavb > 0) { + wavelet_decomposition* bdecomp = new wavelet_decomposition (labco->data+2*datalen, labco->W, labco->H, levwavb, 1, skip, max(1,wavNestedLevels), DaubLen ); + if(!bdecomp->memoryAllocationFailed) { + WaveletcontAllAB(labco, varhue, varchro, *bdecomp, cp, false); + bdecomp->reconstruct(labco->data+2*datalen, cp.strength); + } + delete bdecomp; + } if(numtiles > 1 || (numtiles == 1 && cp.avoi)) { //calculate mask for feathering output tile overlaps @@ -472,56 +581,113 @@ int wavNestedLevels = 1; if (tilerighttoneCurve.hrenabled; + #ifdef _OPENMP -#pragma omp parallel for num_threads(wavNestedLevels) if(wavNestedLevels>1) +#pragma omp parallel for schedule(dynamic,16) num_threads(wavNestedLevels) if(wavNestedLevels>1) #endif for (int i=tiletop; ia[i1][col]); + bv = LVFU(labco->b[i1][col]); + _mm_store_ps(&atan2Buffer[col],xatan2f(bv,av)); + + cv = _mm_sqrt_ps(SQRV(av)+SQRV(bv)); + yv = av / cv; + xv = bv / cv; + xyMask = vmaskf_eq(zerov, cv); + yv = vself(xyMask, onev, yv); + xv = vself(xyMask, zerov, xv); + _mm_store_ps(&yBuffer[col],yv); + _mm_store_ps(&xBuffer[col],xv); + _mm_store_ps(&chprovBuffer[col], cv / c327d68v); + + } + for(;cola[i1][col]; + float b = labco->b[i1][col]; + atan2Buffer[col] = xatan2f(b,a); + float Chprov1=sqrtf(SQR(a) + SQR(b)); + yBuffer[col] = (Chprov1 == 0.f) ? 1.f : a/Chprov1; + xBuffer[col] = (Chprov1 == 0.f) ? 0.f : b/Chprov1; + chprovBuffer[col] = Chprov1/327.68; + } + } +#endif for (int j=tileleft; jL[i1][j1]; - a = labco->a[i1][j1]; - b = labco->b[i1][j1]; if(cp.avoi){//Gamut and Munsell +#ifdef __SSE2__ + float HH = atan2Buffer[j1]; + float Chprov1 = chprovBuffer[j1]; + float2 sincosv; + sincosv.y = yBuffer[j1]; + sincosv.x = xBuffer[j1]; +#else + a = labco->a[i1][j1]; + b = labco->b[i1][j1]; float HH=xatan2f(b,a); - float Chprov1=sqrt(SQR(a/327.68f) + SQR(b/327.68f)); + float Chprov1=sqrtf(SQR(a) + SQR(b)); + float2 sincosv; + sincosv.y = (Chprov1==0.0f) ? 1.f : a/(Chprov1); + sincosv.x = (Chprov1==0.0f) ? 0.f : b/(Chprov1); + Chprov1 /= 327.68f; +#endif + L = labco->L[i1][j1]; float Lprov1=L/327.68f; - float Lprov2 = lab->L[i][j]/327.68f; + float Lprov2 = Lold[i][j]/327.68f; float memChprov=varchro[i1][j1]; - bool highlight = params->toneCurve.hrenabled; float R,G,B; - #ifdef _DEBUG +#ifdef _DEBUG bool neg=false; bool more_rgb=false; - Color::gamutLchonly(HH,Lprov1,Chprov1, R, G, B, wip, highlight, 0.15f, 0.96f, neg, more_rgb); - #else - Color::gamutLchonly(HH,Lprov1,Chprov1, R, G, B, wip, highlight, 0.15f, 0.96f); - #endif + Color::gamutLchonly(HH,sincosv, Lprov1,Chprov1, R, G, B, wip, highlight, 0.15f, 0.96f, neg, more_rgb); +#else + Color::gamutLchonly(HH,sincosv, Lprov1,Chprov1, R, G, B, wip, highlight, 0.15f, 0.96f); +#endif L=Lprov1*327.68f; - float2 sincosv = xsincosf(HH); a=327.68f*Chprov1*sincosv.y;//gamut b=327.68f*Chprov1*sincosv.x;//gamut - { float correctionHue=0.0f; // Munsell's correction float correctlum=0.0f; Lprov1=L/327.68f; - float Chprov=sqrt(SQR(a/327.68f)+ SQR(b/327.68f)); - #ifdef _DEBUG + float Chprov=sqrtf(SQR(a)+ SQR(b))/327.68f; +#ifdef _DEBUG Color::AllMunsellLch(true, Lprov1,Lprov2,HH,Chprov,memChprov,correctionHue,correctlum, MunsDebugInfo); - #else +#else Color::AllMunsellLch(true, Lprov1,Lprov2,HH,Chprov,memChprov,correctionHue,correctlum); - #endif +#endif - if(fabs(correctionHue) < 0.015f) HH+=correctlum; // correct only if correct Munsell chroma very little. - float2 sincosval = xsincosf(HH+correctionHue); - - a=327.68f*Chprov*sincosval.y;// apply Munsell - b=327.68f*Chprov*sincosval.x;//aply Munsell + if(correctionHue!=0.f || correctlum!=0.f) { // only calculate sin and cos if HH changed + if(fabs(correctionHue) < 0.015f) + HH+=correctlum; // correct only if correct Munsell chroma very little. + sincosv = xsincosf(HH+correctionHue); } + + a=327.68f*Chprov*sincosv.y;// apply Munsell + b=327.68f*Chprov*sincosv.x;//aply Munsell + } else { + L = labco->L[i1][j1]; + a = labco->a[i1][j1]; + b = labco->b[i1][j1]; } if(numtiles > 1) { float factor = Vmask[i1]*Hmask[j1]; @@ -537,12 +703,17 @@ int wavNestedLevels = 1; } } } - if(numtiles>1 || cp.avoi) + if(LoldBuffer != NULL) { + delete [] LoldBuffer; + delete [] Lold; + } + if(numtiles>1) delete labco; } } for (int i=0; i1) -#endif - for (int i=0; i lumaref @@ -717,34 +889,35 @@ omp_set_nested(oldNested); float al=(multL-1.f)/av; float bl=1.f; float factorx=1.f; - + #ifdef _OPENMP #pragma omp parallel num_threads(wavNestedLevels) if(wavNestedLevels>1) #endif { - + if(contrast != 0.f) { // contrast = 0.f means that all will be multiplied by 1.f, so we can skip this step #ifdef _OPENMP #pragma omp for #endif for (int i=0; i ave) { + if( WavCoeffs_L0[i]> ave) { float kh = ah*(WavCoeffs_L0[i]/327.68f)+bh; - prov=WavCoeffs_L0[i]; - WavCoeffs_L0[i]=ave+kh*(WavCoeffs_L0[i]-ave); - } else { + prov=WavCoeffs_L0[i]; + WavCoeffs_L0[i]=ave+kh*(WavCoeffs_L0[i]-ave); + } else { float kl = al*(WavCoeffs_L0[i]/327.68f)+1.f; - prov=WavCoeffs_L0[i]; - WavCoeffs_L0[i]=ave-kl*(ave-WavCoeffs_L0[i]); + prov=WavCoeffs_L0[i]; + WavCoeffs_L0[i]=ave-kl*(ave-WavCoeffs_L0[i]); } float diflc=WavCoeffs_L0[i]-prov; diflc*=factorx; WavCoeffs_L0[i] = prov + diflc; } } - + } + if(cp.conres != 0.f || cp.conresH != 0.f) { // cp.conres = 0.f and cp.comresH = 0.f means that all will be multiplied by 1.f, so we can skip this step #ifdef _OPENMP #pragma omp for nowait #endif @@ -780,7 +953,7 @@ omp_set_nested(oldNested); WavCoeffs_L0[i] *= (1.f+(LL100*athH+bthH)/200.f); } } - + } #ifdef _OPENMP #pragma omp for schedule(dynamic) collapse(2) #endif @@ -792,7 +965,7 @@ omp_set_nested(oldNested); float ** WavCoeffs_L = WaveletCoeffs_L.level_coeffs(lvl); - ContAllL (labco, varhue, varchrom, WavCoeffs_L, WavCoeffs_L0, lvl, dir, cp, Wlvl_L, Hlvl_L); + ContAllL (labco, varhue, varchrom, WavCoeffs_L, WavCoeffs_L0, lvl, dir, cp, Wlvl_L, Hlvl_L, skip); } } } @@ -802,18 +975,17 @@ omp_set_nested(oldNested); struct cont_params cp, const bool useChannelA){ int maxlvl = WaveletCoeffs_ab.maxlevel(); - int W_L = WaveletCoeffs_ab.level_W(1); - int H_L = WaveletCoeffs_ab.level_H(1); + int W_L = WaveletCoeffs_ab.level_W(0); + int H_L = WaveletCoeffs_ab.level_H(0); float * WavCoeffs_ab0 = WaveletCoeffs_ab.coeff0; - - - #ifdef _OPENMP #pragma omp parallel num_threads(wavNestedLevels) if(wavNestedLevels>1) #endif { + if(cp.chrores != 0.f) { // cp.chrores == 0.f means all will be multiplied by 1.f, so we can skip the processing of residual + #ifdef _OPENMP #pragma omp for nowait #endif @@ -858,6 +1030,7 @@ omp_set_nested(oldNested); } WavCoeffs_ab0[i]*=(1.f+cp.chrores*(scale)/100.f); } + } #ifdef _OPENMP #pragma omp for schedule(dynamic) collapse(2) @@ -882,11 +1055,32 @@ omp_set_nested(oldNested); //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void ImProcFunctions::ContAllL (LabImage * labco, float ** varhue, float **varchrom, float ** WavCoeffs_L, float * WavCoeffs_L0, int level, int dir, struct cont_params cp, - int W_L, int H_L) + int W_L, int H_L, int skip) { - const float eps = 0.01f; - //float thr= params->wavelet.thres; + static const float scales[10] = {1.f,2.f,4.f,8.f,16.f,32.f,64.f,128.f,256.f,512.f}; + float scaleskip[10]; + for(int sc=0;sc<10;sc++) + scaleskip[sc]=scales[sc]/skip; + float atten01234 = 0.80f; + + if(cp.val > 0) {//edge + float rad = ((float)cp.rad)/60.f;//radius ==> not too high value to avoid artifacts + float value = ((float)cp.val)/8.f;//strength + //value /= skip; + if (scaleskip[1] < 1.f) value *= (atten01234*scaleskip[1]);//for zoom < 100% reduce strength...I choose level 1...but!! + float al0 = 1.f + ((float)cp.til)/50.f; + float al10 =1.0f;//arbitrary value ==> less = take into account high levels + float ak =-(al0-al10)/10.f;//10 = maximum levels + float bk =al0; + float koef = ak*level+bk;//modulate for levels : more levels high, more koef low ==> concentrated action on low levelsn but without forfot high levels + float edge = 1.f + value * exp (-pow(fabs(rad - level),koef));//estimate edge "pseudo variance" + for (int i=0; iwavelet.Lmethod.data())-1; + choicelevel = choicelevel == -1 ? 4 : choicelevel; +/* int choicelevel=0; - if(params->wavelet.Lmethod=="0_") choicelevel=0; - else if(params->wavelet.Lmethod=="1_") choicelevel=1; - else if(params->wavelet.Lmethod=="2_") choicelevel=2; - else if(params->wavelet.Lmethod=="3_") choicelevel=3; - else if(params->wavelet.Lmethod=="4_") choicelevel=4; - else if(params->wavelet.Lmethod=="5_") choicelevel=5; - else if(params->wavelet.Lmethod=="6_") choicelevel=6; - else if(params->wavelet.Lmethod=="7_") choicelevel=7; - else if(params->wavelet.Lmethod=="8_") choicelevel=8; + if(params->wavelet.Lmethod=="1_") choicelevel=0; + else if(params->wavelet.Lmethod=="2_") choicelevel=1; + else if(params->wavelet.Lmethod=="3_") choicelevel=2; + else if(params->wavelet.Lmethod=="4_") choicelevel=3; + else if(params->wavelet.Lmethod=="5_") choicelevel=4; + else if(params->wavelet.Lmethod=="6_") choicelevel=5; + else if(params->wavelet.Lmethod=="7_") choicelevel=6; + else if(params->wavelet.Lmethod=="8_") choicelevel=7; + else if(params->wavelet.Lmethod=="9_") choicelevel=8; +*/ int choiceClevel=0; if(params->wavelet.CLmethod=="one") choiceClevel=0; else if(params->wavelet.CLmethod=="inf") choiceClevel=1; @@ -1017,22 +1211,23 @@ omp_set_nested(oldNested); else if(params->wavelet.Dirmethod=="all") choiceDir=0; // printf("LUm lev=%d clev=%d dir=%d\n",choicelevel,choiceClevel,choiceDir); - if(choiceClevel==0){ - if(choiceDir==0){ + if(choiceClevel==0) { + if(choiceDir==0) { + if(level == 0) + for (int i=0; i= choicelevel){ + } else if(choiceClevel==1) { + if(choiceDir==0) { + if(level >= choicelevel) { for (int dir=1; dir<4; dir++) { for (int i=0; i= choicelevel){ - + if(level >= choicelevel) { for (int i=0; iwavelet.thres; float cpMul = cp.mul[level]; - if(cpMul != 0.f && cp.CHmet==2 && cp.chro != 0.f) { // cpMul == 0.f means all will be multiplied by 1.f, so we can skip this + if(cpMul != 0.f && cp.CHmet==2 && cp.chro != 0.f) { // cpMul == 0.f or cp.chro = 0.f means all will be multiplied by 1.f, so we can skip this const float skinprot = params->wavelet.skinprotect; const float skinprotneg = -skinprot; const float factorHard = (1.f - skinprotneg/100.f); const float cpChrom = cp.chro; //to adjust increase contrast with local contrast - bool useChromAndHue = (skinprot != 0.f); - float modchro; - + bool useSkinControl = (skinprot != 0.f); + float alphaC =(1024.f + 15.f *cpMul*cpChrom/50.f)/1024.f ; for (int i=0; iL[ii*2][jj*2]; - float LL100=LL/327.68f; + float LL100 = labco->L[ii*2][jj*2]/327.68f; float modhue = varhue[ii][jj]; - modchro = varchrom[ii*2][jj*2]; + float modchro = varchrom[ii*2][jj*2]; // hue chroma skin with initial lab datas - scale=1.f; + float scale=1.f; if(skinprot > 0.f){ Color::SkinSatCbdl2 (LL100, modhue, modchro, skinprot, scale, true, cp.b_l, cp.t_l, cp.t_r, cp.b_r, 0); //0 for skin and extand } else if(skinprot < 0.f){ - Color::SkinSatCbdl2 (LL100, modhue, modchro, skinprotneg, scale, false, cp.b_l, cp.t_l, cp.t_r, cp.b_r, 0); - if (scale == 1.f) - scale=factorHard; - else - scale=1.f; + Color::SkinSatCbdl2 (LL100, modhue, modchro, skinprotneg, scale, false, cp.b_l, cp.t_l, cp.t_r, cp.b_r, 0); + scale = (scale == 1.f) ? factorHard : 1.f; } + alphaC =(1024.f + 15.f *cpMul*cpChrom*scale/50.f)/1024.f ; } - float alphaC =(1024.f + 15.f *cpMul*cpChrom*scale*scaleSK/50.f)/1024.f ; - WavCoeffs_ab[dir][i]*=alphaC; + WavCoeffs_ab[dir][i] *= alphaC; } } //Curve chro + float cpMulC = cp.mulC[level]; + if(cp.curv && cp.CHmet!=2 && level < 9 && cpMulC != 0.f) { // cpMulC == 0.f means all will be multiplied by 1.f, so we can skip + float modchro, modhue, kClev; + const float skinprot = params->wavelet.skinprotect; + const float skinprotneg = -skinprot; + const float factorHard = (1.f - skinprotneg/100.f); + bool useSkinControl = (skinprot != 0.f); + + for (int i=0; iL[ii*2][jj*2]; + float LL100=LL/327.68f; + float scale=1.f; + modchro = varchrom[ii*2][jj*2]; + + if(useSkinControl) { + // hue chroma skin with initial lab datas + modhue = varhue[ii][jj]; + scale=1.f; + if(skinprot > 0.f){ + Color::SkinSatCbdl2 (LL100, modhue, modchro, skinprot, scale, true, cp.b_l, cp.t_l, cp.t_r, cp.b_r, 1); //1 for curve + } + else if(skinprot < 0.f){ + Color::SkinSatCbdl2 (LL100, modhue, modchro, skinprotneg, scale, false, cp.b_l, cp.t_l, cp.t_r, cp.b_r, 1); + scale = (scale == 1.f) ? factorHard : 1.f; + } + } + float beta = (1024.f + 20.f * cpMulC * scale)/1024.f ; + if(beta < 0.02f) + beta=0.02f; + kClev = beta; + if(cp.CHmet==1){ + if(level < cp.chrom) { + //linear for saturated + if((modchro > cp.t_lsat && modchro < cp.t_rsat)) + kClev=beta; + else if((modchro > cp.b_lsat && modchro <= cp.t_lsat)) { + float aaal=(1.f-beta)/(cp.b_lsat-cp.t_lsat); + float bbal=1.f-aaal*cp.b_lsat; + kClev=aaal*modchro+bbal; + } else if((modchro > cp.t_rsat && modchro <= cp.b_rsat)) { + float aaar=(beta-1.f)/(cp.t_rsat-cp.b_rsat); + float bbbr=1.f-cp.b_rsat*aaar; + kClev=aaar*modchro+bbbr; + } else + kClev=1.f; + } else { + //linear for pastel + if((modchro > cp.t_lpast && modchro < cp.t_rpast)) + kClev=beta; + else if((modchro > cp.b_lpast && modchro <= cp.t_lpast)) { + float aaalS=(1.f-beta)/(cp.b_lpast-cp.t_lpast); + float bbalS=1.f-aaalS*cp.b_lpast; + kClev=aaalS*modchro+bbalS; + } else if((modchro > cp.t_rpast && modchro <= cp.b_rpast)) { + float aaarS=(beta-1.f)/(cp.t_rpast-cp.b_rpast); + float bbbrS=1.f-cp.b_rpast*aaarS; + kClev=aaarS*modchro+bbbrS; + } else + kClev=1.f; + } + } + else if(cp.CHmet==0) + kClev=beta; + WavCoeffs_ab[dir][i] *= kClev; + } + } + bool useOpacity; float mulOpacity; if(useChannelA) { @@ -1143,89 +1393,29 @@ omp_set_nested(oldNested); useOpacity = cp.opaBY; mulOpacity = cp.mulopaBY[level]; } - if(cp.curv && cp.CHmet!=2 && level < 9) { - float modchro, modhue, kLlev, kClev; - float cpMulC = cp.mulC[level]; - const float skinprot = params->wavelet.skinprotect; - const float skinprotneg = -skinprot; - const float factorHard = (1.f - skinprotneg/100.f); - bool skinControl = (skinprot != 0.f); - - for (int i=0; iL[ii*2][jj*2]; - float LL100=LL/327.68f; - float scale=1.f; - modchro = varchrom[ii*2][jj*2]; - float modhue = varhue[ii][jj]; - - if(skinControl) { - // hue chroma skin with initial lab datas - modhue = varhue[ii][jj]; - - scale=1.f; - if(skinprot > 0.f){ - Color::SkinSatCbdl2 (LL100, modhue, modchro, skinprot, scale, true, cp.b_l, cp.t_l, cp.t_r, cp.b_r, 1); //1 for curve - } - else if(skinprot < 0.f){ - Color::SkinSatCbdl2 (LL100, modhue, modchro, skinprotneg, scale, false, cp.b_l, cp.t_l, cp.t_r, cp.b_r, 1); - if (scale == 1.f) { scale=factorHard;} - else scale=1.f; - } - } - float scaleSK =1.f; - float beta = (1024.f + 20.f *(float) cpMulC*scale*scaleSK)/1024.f ; - if(beta < 0.02f) beta=0.02f; - //linear for saturated - float aaal=(1.f-beta)/(cp.b_lsat-cp.t_lsat); - float bbal=1.f-aaal*cp.b_lsat; - float aaar=(beta-1.f)/(cp.t_rsat-cp.b_rsat); - float bbbr=1.f-cp.b_rsat*aaar; - //linear for pastel - float aaalS=(1.f-beta)/(cp.b_lpast-cp.t_lpast); - float bbalS=1.f-aaalS*cp.b_lpast; - float aaarS=(beta-1.f)/(cp.t_rpast-cp.b_rpast); - float bbbrS=1.f-cp.b_rpast*aaarS; - kClev=beta; - if(cp.CHmet==1){ - if(level < cp.chrom) { - if((modchro > cp.t_lsat && modchro < cp.t_rsat)) kClev=beta; - else if((modchro > cp.b_lsat && modchro <= cp.t_lsat)) kClev=aaal*modchro+bbal; - else if((modchro > cp.t_rsat && modchro <= cp.b_rsat)) kClev=aaar*modchro+bbbr; - else kClev=1.f; - } - if(level >= cp.chrom) { - if((modchro > cp.t_lpast && modchro < cp.t_rpast)) kClev=beta; - else if((modchro > cp.b_lpast && modchro <= cp.t_lpast)) kClev=aaalS*modchro+bbalS; - else if((modchro > cp.t_rpast && modchro <= cp.b_rpast)) kClev=aaarS*modchro+bbbrS; - else kClev=1.f; - } - } - else if(cp.CHmet==0)kClev=beta; - WavCoeffs_ab[dir][i]*=kClev; - } - } - if(useOpacity && level < 9) { //toning - float betaRG = (1024.f + 20.f *(float) mulOpacity)/1024.f ; + if(useOpacity && level < 9 && mulOpacity != 0.f) { //toning + float beta = (1024.f + 20.f * mulOpacity)/1024.f ; for (int i=0; iwavelet.Lmethod.data())-1; + choicelevel = choicelevel == -1 ? 4 : choicelevel; +/* int choicelevel=0; - if(params->wavelet.Lmethod=="0_") choicelevel=0; - else if(params->wavelet.Lmethod=="1_") choicelevel=1; - else if(params->wavelet.Lmethod=="2_") choicelevel=2; - else if(params->wavelet.Lmethod=="3_") choicelevel=3; - else if(params->wavelet.Lmethod=="4_") choicelevel=4; - else if(params->wavelet.Lmethod=="5_") choicelevel=5; - else if(params->wavelet.Lmethod=="6_") choicelevel=6; - else if(params->wavelet.Lmethod=="7_") choicelevel=7; - else if(params->wavelet.Lmethod=="8_") choicelevel=8; + if(params->wavelet.Lmethod=="1_") choicelevel=0; + else if(params->wavelet.Lmethod=="2_") choicelevel=1; + else if(params->wavelet.Lmethod=="3_") choicelevel=2; + else if(params->wavelet.Lmethod=="4_") choicelevel=3; + else if(params->wavelet.Lmethod=="5_") choicelevel=4; + else if(params->wavelet.Lmethod=="6_") choicelevel=5; + else if(params->wavelet.Lmethod=="7_") choicelevel=6; + else if(params->wavelet.Lmethod=="8_") choicelevel=7; + else if(params->wavelet.Lmethod=="9_") choicelevel=8; +*/ int choiceClevel=0; if(params->wavelet.CLmethod=="one") choiceClevel=0; else if(params->wavelet.CLmethod=="inf") choiceClevel=1; @@ -1236,72 +1426,72 @@ omp_set_nested(oldNested); else if(params->wavelet.Dirmethod=="two") choiceDir=2; else if(params->wavelet.Dirmethod=="thr") choiceDir=3; else if(params->wavelet.Dirmethod=="all") choiceDir=0; - // printf("CHRO lev=%d clev=%d dir=%d\n",choicelevel,choiceClevel,choiceDir); - - if(choiceClevel==0){ - if(choiceDir==0){ - if(level != choicelevel){ - for (int dir=1; dir<4; dir++) { + // printf("LUm lev=%d clev=%d dir=%d\n",choicelevel,choiceClevel,choiceDir); + if(choiceClevel==0) { + if(choiceDir==0) { + if(level == 0) for (int i=0; i= choicelevel) { + for (int dir=1; dir<4; dir++) { + for (int i=0; i= choicelevel) { + for (int i=0; i= choicelevel){ - for (int dir=1; dir<4; dir++) { - for (int i=0; i= choicelevel){ - - for (int i=0; iwavelet.enabled) keyFile.set_boolean ("Wavelet", "Enabled", wavelet.enabled); + if (!pedited || pedited->wavelet.strength) keyFile.set_integer ("Wavelet", "Strength", wavelet.strength); if (!pedited || pedited->wavelet.thres) keyFile.set_integer ("Wavelet", "MaxLev", wavelet.thres); if (!pedited || pedited->wavelet.Tilesmethod) keyFile.set_string ("Wavelet", "TilesMethod", wavelet.Tilesmethod); if (!pedited || pedited->wavelet.CLmethod) keyFile.set_string ("Wavelet", "ChoiceLevMethod", wavelet.CLmethod); if (!pedited || pedited->wavelet.Lmethod) keyFile.set_string ("Wavelet", "LevMethod", wavelet.Lmethod); if (!pedited || pedited->wavelet.Dirmethod) keyFile.set_string ("Wavelet", "DirMethod", wavelet.Dirmethod); - // if (!pedited || pedited->wavelet.tiles) keyFile.set_integer ("Wavelet", "Tiles", wavelet.tiles); for(int i = 0; i < 9; i++) { std::stringstream ss; - ss << "Contrast" << i; + ss << "Contrast" << (i+1); if (!pedited || pedited->wavelet.c[i]) keyFile.set_integer("Wavelet", ss.str(), wavelet.c[i]); } if (!pedited || pedited->wavelet.sup) keyFile.set_integer ("Wavelet", "ContExtra", wavelet.sup); @@ -1566,9 +1569,13 @@ int ProcParams::save (Glib::ustring fname, Glib::ustring fname2, bool fnameAbsol Glib::ArrayHandle thresh (wavelet.hueskin.value, 4, Glib::OWNERSHIP_NONE); keyFile.set_integer_list("Wavelet", "Hueskin", thresh); } + + if (!pedited || pedited->wavelet.edgrad) keyFile.set_integer ("Wavelet", "Edgrad", wavelet.edgrad); + if (!pedited || pedited->wavelet.edgval) keyFile.set_integer ("Wavelet", "Edgval", wavelet.edgval); + if (!pedited || pedited->wavelet.edgthresh) keyFile.set_integer ("Wavelet", "ThrEdg", wavelet.edgthresh); + if (!pedited || pedited->wavelet.strength) keyFile.set_integer ("Wavelet", "Strength", wavelet.strength); if (!pedited || pedited->wavelet.avoid) keyFile.set_boolean ("Wavelet", "AvoidColorShift", wavelet.avoid); - if (!pedited || pedited->wavelet.rescon) keyFile.set_integer ("Wavelet", "ResidualcontShadow", wavelet.rescon); if (!pedited || pedited->wavelet.resconH) keyFile.set_integer ("Wavelet", "ResidualcontHighlight", wavelet.resconH); if (!pedited || pedited->wavelet.thr) keyFile.set_integer ("Wavelet", "ThresholdResidShadow", wavelet.thr); @@ -1579,7 +1586,7 @@ int ProcParams::save (Glib::ustring fname, Glib::ustring fname2, bool fnameAbsol Glib::ArrayHandle thresh (wavelet.hueskin2.value, 4, Glib::OWNERSHIP_NONE); keyFile.set_integer_list("Wavelet", "HueRange", thresh); } - if (!pedited || pedited->wavelet.unif) keyFile.set_integer ("Wavelet", "Contrast", wavelet.unif); + if (!pedited || pedited->wavelet.contrast) keyFile.set_integer ("Wavelet", "Contrast", wavelet.contrast); // save directional pyramid wavelet parameters @@ -2298,7 +2305,7 @@ if (keyFile.has_group ("Color Management")) { // load wavelet wavelet parameters if (keyFile.has_group ("Wavelet")) { if (keyFile.has_key ("Wavelet", "Enabled")) { wavelet.enabled = keyFile.get_boolean ("Wavelet", "Enabled"); if (pedited) pedited->wavelet.enabled = true; } - + if (keyFile.has_key ("Wavelet", "Strength")) { wavelet.strength = keyFile.get_integer ("Wavelet", "Strength"); if (pedited) pedited->wavelet.strength = true; } if (keyFile.has_key ("Wavelet", "Median")) {wavelet.median = keyFile.get_boolean ("Wavelet", "Median");if (pedited) pedited->wavelet.median = true;} if (keyFile.has_key ("Wavelet", "AvoidColorShift")) {wavelet.avoid = keyFile.get_boolean ("Wavelet", "AvoidColorShift");if (pedited) pedited->wavelet.avoid = true;} if (keyFile.has_key ("Wavelet", "LevMethod")) {wavelet.Lmethod = keyFile.get_string ("Wavelet", "LevMethod"); if (pedited) pedited->wavelet.Lmethod = true; } @@ -2307,10 +2314,9 @@ if (keyFile.has_group ("Wavelet")) { if (keyFile.has_key ("Wavelet", "CHromaMethod")) {wavelet.CHmethod = keyFile.get_string ("Wavelet", "CHromaMethod"); if (pedited) pedited->wavelet.CHmethod = true; } if (keyFile.has_key ("Wavelet", "HSMethod")) {wavelet.HSmethod = keyFile.get_string ("Wavelet", "HSMethod"); if (pedited) pedited->wavelet.HSmethod = true; } if (keyFile.has_key ("Wavelet", "DirMethod")) {wavelet.Dirmethod = keyFile.get_string ("Wavelet", "DirMethod"); if (pedited) pedited->wavelet.Dirmethod = true; } - if (keyFile.has_key ("Wavelet", "Tiles")) {wavelet.tiles = keyFile.get_integer ("Wavelet", "Tiles"); if (pedited) pedited->wavelet.tiles = true; } if (keyFile.has_key ("Wavelet", "ResidualcontShadow")) {wavelet.rescon = keyFile.get_integer ("Wavelet", "ResidualcontShadow"); if (pedited) pedited->wavelet.rescon = true; } - if (keyFile.has_key ("Wavelet", "ResidualcontHighLight")) {wavelet.resconH = keyFile.get_integer ("Wavelet", "ResidualcontHighLight"); if (pedited) pedited->wavelet.resconH = true; } - if (keyFile.has_key ("Wavelet", "Residualchroma")) {wavelet.reschro = keyFile.get_integer ("Wavelet", "Residualchroma"); if (pedited) pedited->wavelet.reschro = true; } + if (keyFile.has_key ("Wavelet", "ResidualcontHighlight")) {wavelet.resconH = keyFile.get_integer ("Wavelet", "ResidualcontHighlight"); if (pedited) pedited->wavelet.resconH = true; } + if (keyFile.has_key ("Wavelet", "Residualchroma")) {wavelet.reschro = keyFile.get_integer ("Wavelet", "Residualchroma"); if (pedited) pedited->wavelet.reschro = true; } if (keyFile.has_key ("Wavelet", "ContExtra")) {wavelet.sup = keyFile.get_integer ("Wavelet", "ContExtra"); if (pedited) pedited->wavelet.sup = true; } if (keyFile.has_key ("Wavelet", "HueRangeResidual")) {wavelet.sky = keyFile.get_double ("Wavelet", "HueRangeResidual"); if (pedited) pedited->wavelet.sky = true; } if (keyFile.has_key ("Wavelet", "MaxLev")) {wavelet.thres = keyFile.get_integer ("Wavelet", "MaxLev"); if (pedited) pedited->wavelet.thres = true; } @@ -2318,9 +2324,12 @@ if (keyFile.has_group ("Wavelet")) { if (keyFile.has_key ("Wavelet", "ThresholdShadow")) {wavelet.threshold2 = keyFile.get_integer ("Wavelet", "ThresholdShadow"); if (pedited) pedited->wavelet.threshold2 = true; } if (keyFile.has_key ("Wavelet", "ThresholdChroma")) {wavelet.chroma = keyFile.get_integer ("Wavelet", "ThresholdChroma"); if (pedited) pedited->wavelet.chroma = true; } if (keyFile.has_key ("Wavelet", "ChromaLink")) {wavelet.chro = keyFile.get_integer ("Wavelet", "ChromaLink"); if (pedited) pedited->wavelet.chro = true; } - if (keyFile.has_key ("Wavelet", "Contrast")) {wavelet.unif = keyFile.get_integer ("Wavelet", "Contrast"); if (pedited) pedited->wavelet.unif = true; } + if (keyFile.has_key ("Wavelet", "Contrast")) {wavelet.contrast = keyFile.get_integer ("Wavelet", "Contrast"); if (pedited) pedited->wavelet.contrast = true; } + if (keyFile.has_key ("Wavelet", "Edgrad")) {wavelet.edgrad = keyFile.get_integer ("Wavelet", "Edgrad"); if (pedited) pedited->wavelet.edgrad = true; } + if (keyFile.has_key ("Wavelet", "Edgval")) {wavelet.edgval = keyFile.get_integer ("Wavelet", "Edgval"); if (pedited) pedited->wavelet.edgval = true; } + if (keyFile.has_key ("Wavelet", "ThrEdg")) {wavelet.edgthresh = keyFile.get_integer ("Wavelet", "ThrEdg"); if (pedited) pedited->wavelet.edgthresh = true; } if (keyFile.has_key ("Wavelet", "ThresholdResidShadow")) {wavelet.thr = keyFile.get_integer ("Wavelet", "ThresholdResidShadow"); if (pedited) pedited->wavelet.thr = true; } - if (keyFile.has_key ("Wavelet", "ThresholdResidHighLight")) {wavelet.thr = keyFile.get_integer ("Wavelet", "ThresholdResidHighLight"); if (pedited) pedited->wavelet.thrH = true; } + if (keyFile.has_key ("Wavelet", "ThresholdResidHighLight")) {wavelet.thrH = keyFile.get_integer ("Wavelet", "ThresholdResidHighLight"); if (pedited) pedited->wavelet.thrH = true; } if (keyFile.has_key ("Wavelet", "ChromaCurve")) {wavelet.clvcurve = keyFile.get_double_list ("Wavelet", "ChromaCurve"); if (pedited) pedited->wavelet.clvcurve = true; } if (keyFile.has_key ("Wavelet", "OpacityCurveRG")) { wavelet.opacityCurveRG = keyFile.get_double_list ("Wavelet", "OpacityCurveRG"); if (pedited) pedited->wavelet.opacityCurveRG = true; } if (keyFile.has_key ("Wavelet", "OpacityCurveBY")) { wavelet.opacityCurveBY = keyFile.get_double_list ("Wavelet", "OpacityCurveBY"); if (pedited) pedited->wavelet.opacityCurveBY = true; } @@ -2361,7 +2370,7 @@ if (keyFile.has_group ("Wavelet")) { for(int i = 0; i < 9; i ++) { std::stringstream ss; - ss << "Contrast" << i; + ss << "Contrast" << (i+1); if(keyFile.has_key ("Wavelet", ss.str())) {wavelet.c[i] = keyFile.get_integer ("Wavelet", ss.str()); if (pedited) pedited->wavelet.c[i] = true;} } } @@ -2893,7 +2902,6 @@ bool ProcParams::operator== (const ProcParams& other) { && wavelet.CHmethod == other.wavelet.CHmethod && wavelet.HSmethod == other.wavelet.HSmethod && wavelet.Dirmethod == other.wavelet.Dirmethod - && wavelet.tiles == other.wavelet.tiles && wavelet.rescon == other.wavelet.rescon && wavelet.resconH == other.wavelet.resconH && wavelet.reschro == other.wavelet.reschro @@ -2903,7 +2911,10 @@ bool ProcParams::operator== (const ProcParams& other) { && wavelet.threshold == other.wavelet.threshold && wavelet.chroma == other.wavelet.chroma && wavelet.chro == other.wavelet.chro - && wavelet.unif == other.wavelet.unif + && wavelet.contrast == other.wavelet.contrast + && wavelet.edgrad == other.wavelet.edgrad + && wavelet.edgval == other.wavelet.edgval + && wavelet.edgthresh == other.wavelet.edgthresh && wavelet.thr == other.wavelet.thr && wavelet.thrH == other.wavelet.thrH && wavelet.threshold == other.wavelet.threshold @@ -2918,6 +2929,7 @@ bool ProcParams::operator== (const ProcParams& other) { && wavelet.opacityCurveBY == other.wavelet.opacityCurveBY && wavelet.clvcurve == other.wavelet.clvcurve && wavelet.skinprotect == other.wavelet.skinprotect + && wavelet.strength == other.wavelet.strength && dirpyrequalizer == other.dirpyrequalizer // && dirpyrequalizer.algo == other.dirpyrequalizer.algo && dirpyrequalizer.hueskin == other.dirpyrequalizer.hueskin diff --git a/rtengine/procparams.h b/rtengine/procparams.h index 05a7d2cc0..41f9fdae7 100644 --- a/rtengine/procparams.h +++ b/rtengine/procparams.h @@ -862,6 +862,7 @@ class WaveletParams { bool enabled; bool median; bool avoid; + int strength; int c[9]; Glib::ustring Lmethod; Glib::ustring CLmethod; @@ -869,7 +870,6 @@ class WaveletParams { Glib::ustring CHmethod; Glib::ustring Dirmethod; Glib::ustring HSmethod; - int tiles; int rescon; int resconH; int reschro; @@ -880,7 +880,10 @@ class WaveletParams { int chro; int threshold; int threshold2; - int unif; + int contrast; + int edgrad; + int edgval; + int edgthresh; int thr; int thrH; double skinprotect; diff --git a/rtengine/refreshmap.cc b/rtengine/refreshmap.cc index 16fce5218..075e229aa 100644 --- a/rtengine/refreshmap.cc +++ b/rtengine/refreshmap.cc @@ -358,7 +358,10 @@ DIRPYREQUALIZER, // EvWavrescon DIRPYREQUALIZER, // EvWavreschro DIRPYREQUALIZER, // EvWavresconH DIRPYREQUALIZER, // EvWavthrH -DIRPYREQUALIZER // EvWavHueskin2 +DIRPYREQUALIZER, // EvWavHueskin2 +DIRPYREQUALIZER, // EvWavedgrad +DIRPYREQUALIZER, // EvWavedgval +DIRPYREQUALIZER // EvWavStrngth }; diff --git a/rtengine/settings.h b/rtengine/settings.h index ddb30b726..0c65d8494 100644 --- a/rtengine/settings.h +++ b/rtengine/settings.h @@ -64,7 +64,7 @@ namespace rtengine { double nrautomax; double nrhigh; int nrwavlevel; - + bool daubech; bool ciebadpixgauss; int CRI_color; // N� for display Lab value ; 0 disabled int denoiselabgamma; // 0=gamma 26 11 1=gamma 40 5 2 =gamma 55 10 diff --git a/rtgui/addsetids.h b/rtgui/addsetids.h index 94443e042..da7d8ccbd 100644 --- a/rtgui/addsetids.h +++ b/rtgui/addsetids.h @@ -94,12 +94,16 @@ #define ADDSET_WA_THRESHOLD2 86 #define ADDSET_WA_CHRO 87 #define ADDSET_WA_CHROMA 88 -#define ADDSET_WA_UNIF 89 +#define ADDSET_WA_CONTRAST 89 #define ADDSET_WA_RESCON 90 #define ADDSET_WA_RESCONH 91 #define ADDSET_WA_RESCHRO 92 #define ADDSET_WA_SKYPROTECT 93 +#define ADDSET_WA_EDGRAD 94 +#define ADDSET_WA_EDGVAL 95 +#define ADDSET_WA_STRENGTH 96 + // When adding items, make sure to update ADDSET_PARAM_NUM -#define ADDSET_PARAM_NUM 94 // THIS IS USED AS A DELIMITER!! +#define ADDSET_PARAM_NUM 97 // THIS IS USED AS A DELIMITER!! #endif diff --git a/rtgui/batchtoolpanelcoord.cc b/rtgui/batchtoolpanelcoord.cc index c6a46146a..a227b8c24 100644 --- a/rtgui/batchtoolpanelcoord.cc +++ b/rtgui/batchtoolpanelcoord.cc @@ -148,7 +148,7 @@ void BatchToolPanelCoordinator::initSession () { shadowshighlights->setAdjusterBehavior (false, false, false); dirpyrequalizer->setAdjusterBehavior (false, false, false); - wavelet->setAdjusterBehavior (false, false, false,false,false,false,false,false,false,false,false,false,false,false); + wavelet->setAdjusterBehavior (false, false, false,false,false,false,false,false,false,false,false,false,false,false,false,false,false); dirpyrdenoise->setAdjusterBehavior (false, false,false,false,false,false, false); bayerpreprocess->setAdjusterBehavior (false, false); rawcacorrection->setAdjusterBehavior (false); @@ -186,7 +186,7 @@ void BatchToolPanelCoordinator::initSession () { blackwhite->setAdjusterBehavior (options.baBehav[ADDSET_BLACKWHITE_HUES],options.baBehav[ADDSET_BLACKWHITE_GAMMA]); shadowshighlights->setAdjusterBehavior (options.baBehav[ADDSET_SH_HIGHLIGHTS], options.baBehav[ADDSET_SH_SHADOWS], options.baBehav[ADDSET_SH_LOCALCONTRAST]); dirpyrequalizer->setAdjusterBehavior (options.baBehav[ADDSET_DIRPYREQ], options.baBehav[ADDSET_DIRPYREQ_THRESHOLD], options.baBehav[ADDSET_DIRPYREQ_SKINPROTECT]); - wavelet->setAdjusterBehavior (options.baBehav[ADDSET_WA], options.baBehav[ADDSET_WA_THRESHOLD], options.baBehav[ADDSET_WA_THRESHOLD2],options.baBehav[ADDSET_WA_THRES],options.baBehav[ADDSET_WA_CHRO],options.baBehav[ADDSET_WA_CHROMA],options.baBehav[ADDSET_WA_UNIF],options.baBehav[ADDSET_WA_SKINPROTECT],options.baBehav[ADDSET_WA_RESCHRO],options.baBehav[ADDSET_WA_RESCON],options.baBehav[ADDSET_WA_RESCONH],options.baBehav[ADDSET_WA_THRR],options.baBehav[ADDSET_WA_THRRH],options.baBehav[ADDSET_WA_SKYPROTECT] ); + wavelet->setAdjusterBehavior (options.baBehav[ADDSET_WA], options.baBehav[ADDSET_WA_THRESHOLD], options.baBehav[ADDSET_WA_THRESHOLD2],options.baBehav[ADDSET_WA_THRES],options.baBehav[ADDSET_WA_CHRO],options.baBehav[ADDSET_WA_CHROMA],options.baBehav[ADDSET_WA_CONTRAST],options.baBehav[ADDSET_WA_SKINPROTECT],options.baBehav[ADDSET_WA_RESCHRO],options.baBehav[ADDSET_WA_RESCON],options.baBehav[ADDSET_WA_RESCONH],options.baBehav[ADDSET_WA_THRR],options.baBehav[ADDSET_WA_THRRH],options.baBehav[ADDSET_WA_SKYPROTECT], options.baBehav[ADDSET_WA_EDGRAD],options.baBehav[ADDSET_WA_EDGVAL],options.baBehav[ADDSET_WA_STRENGTH]); dirpyrdenoise->setAdjusterBehavior (options.baBehav[ADDSET_DIRPYRDN_LUMA],options.baBehav[ADDSET_DIRPYRDN_LUMDET],options.baBehav[ADDSET_DIRPYRDN_CHROMA],options.baBehav[ADDSET_DIRPYRDN_CHROMARED],options.baBehav[ADDSET_DIRPYRDN_CHROMABLUE], options.baBehav[ADDSET_DIRPYRDN_GAMMA], options.baBehav[ADDSET_DIRPYRDN_PASSES]); bayerpreprocess->setAdjusterBehavior (options.baBehav[ADDSET_PREPROCESS_LINEDENOISE], options.baBehav[ADDSET_PREPROCESS_GREENEQUIL]); rawcacorrection->setAdjusterBehavior (options.baBehav[ADDSET_RAWCACORR]); @@ -293,7 +293,7 @@ void BatchToolPanelCoordinator::initSession () { if (options.baBehav[ADDSET_WA_SKINPROTECT]) pparams.wavelet.skinprotect = 0; if (options.baBehav[ADDSET_WA_CHRO]) pparams.wavelet.chro = 0; if (options.baBehav[ADDSET_WA_CHROMA]) pparams.wavelet.chroma = 0; - if (options.baBehav[ADDSET_WA_UNIF]) pparams.wavelet.unif = 0; + if (options.baBehav[ADDSET_WA_CONTRAST]) pparams.wavelet.contrast = 0; if (options.baBehav[ADDSET_WA_THRES]) pparams.wavelet.thres = 0; if (options.baBehav[ADDSET_WA_RESCON]) pparams.wavelet.rescon = 0; if (options.baBehav[ADDSET_WA_RESCONH]) pparams.wavelet.resconH = 0; @@ -301,6 +301,10 @@ void BatchToolPanelCoordinator::initSession () { if (options.baBehav[ADDSET_WA_THRR]) pparams.wavelet.thr = 0; if (options.baBehav[ADDSET_WA_THRRH]) pparams.wavelet.thrH = 0; if (options.baBehav[ADDSET_WA_SKYPROTECT]) pparams.wavelet.sky = 0; + if (options.baBehav[ADDSET_WA_EDGRAD]) pparams.wavelet.edgrad = 0; + if (options.baBehav[ADDSET_WA_EDGVAL]) pparams.wavelet.edgval = 0; + if (options.baBehav[ADDSET_WA_STRENGTH]) pparams.wavelet.strength = 0; + if (options.baBehav[ADDSET_DIRPYRDN_LUMA]) pparams.dirpyrDenoise.luma = 0; diff --git a/rtgui/options.cc b/rtgui/options.cc index 41939ec26..e826bf449 100644 --- a/rtgui/options.cc +++ b/rtgui/options.cc @@ -520,7 +520,7 @@ void Options::setDefaults () { 0, //ADDSET_WA_THRES 0, //ADDSET_WA_CHRO 0, //ADDSET_WA_CHROMA - 0, //ADDSET_WA_UNIF + 0, //ADDSET_WA_CONTRAST 0, //ADDSET_WA_SKINPROTECT 0, //ADDSET_WA_RESCHRO 0, //ADDSET_WA_RESCON @@ -528,6 +528,9 @@ void Options::setDefaults () { 0, //ADDSET_WA_THRR 0, //ADDSET_WA_THRRH 0, //ADDSET_WA_SKYPROTECT + 0, //ADDSET_WA_EDGRAD + 0, //ADDSET_WA_EDGVAL + 0, //ADDSET_WA_STRENGTH }; baBehav = std::vector (babehav, babehav+ADDSET_PARAM_NUM); @@ -581,6 +584,8 @@ void Options::setDefaults () { rtSettings.autocielab=true; rtSettings.denoiselabgamma=2; rtSettings.HistogramWorking = false; + + rtSettings.daubech = false; rtSettings.nrauto = 10;//between 2 and 20 rtSettings.nrautomax = 40;//between 5 and 100 @@ -770,6 +775,7 @@ if (keyFile.has_group ("Performance")) { if (keyFile.has_key ("Performance", "ClutCacheSize")) clutCacheSize = keyFile.get_integer ("Performance", "ClutCacheSize"); if (keyFile.has_key ("Performance", "MaxInspectorBuffers")) maxInspectorBuffers = keyFile.get_integer ("Performance", "MaxInspectorBuffers"); if (keyFile.has_key ("Performance", "PreviewDemosaicFromSidecar")) prevdemo = (prevdemo_t)keyFile.get_integer ("Performance", "PreviewDemosaicFromSidecar"); + if (keyFile.has_key ("Performance", "Daubechies")) rtSettings.daubech = keyFile.get_boolean ("Performance", "Daubechies"); } if (keyFile.has_group ("GUI")) { @@ -1056,6 +1062,7 @@ int Options::saveToFile (Glib::ustring fname) { keyFile.set_integer ("Performance", "ClutCacheSize", clutCacheSize); keyFile.set_integer ("Performance", "MaxInspectorBuffers", maxInspectorBuffers); keyFile.set_integer ("Performance", "PreviewDemosaicFromSidecar", prevdemo); + keyFile.set_boolean ("Performance", "Daubechies", rtSettings.daubech); keyFile.set_string ("Output", "Format", saveFormat.format); keyFile.set_integer ("Output", "JpegQuality", saveFormat.jpegQuality); diff --git a/rtgui/paramsedited.cc b/rtgui/paramsedited.cc index 8b5f18472..4f7618cca 100644 --- a/rtgui/paramsedited.cc +++ b/rtgui/paramsedited.cc @@ -336,6 +336,7 @@ void ParamsEdited::set (bool v) { raw.exPos = v; raw.exPreser = v; wavelet.enabled = v; + wavelet.strength = v; wavelet.median = v; wavelet.avoid = v; wavelet.Lmethod = v; @@ -344,7 +345,6 @@ void ParamsEdited::set (bool v) { wavelet.CHmethod = v; wavelet.HSmethod = v; wavelet.Dirmethod = v; - wavelet.tiles = v; wavelet.rescon = v; wavelet.resconH = v; wavelet.reschro = v; @@ -355,7 +355,10 @@ void ParamsEdited::set (bool v) { wavelet.threshold2 = v; wavelet.chroma = v; wavelet.chro = v; - wavelet.unif = v; + wavelet.contrast = v; + wavelet.edgrad = v; + wavelet.edgval = v; + wavelet.edgthresh = v; wavelet.thr = v; wavelet.thrH = v; wavelet.skinprotect = v; @@ -711,6 +714,7 @@ void ParamsEdited::initFrom (const std::vector raw.exPos = raw.exPos && p.raw.expos == other.raw.expos; raw.exPreser = raw.exPreser && p.raw.preser == other.raw.preser; wavelet.enabled = wavelet.enabled && p.wavelet.enabled == other.wavelet.enabled; + wavelet.strength = wavelet.strength && p.wavelet.strength == other.wavelet.strength; wavelet.median = wavelet.median && p.wavelet.median == other.wavelet.median; wavelet.avoid = wavelet.avoid && p.wavelet.avoid == other.wavelet.avoid; wavelet.Lmethod = wavelet.Lmethod && p.wavelet.Lmethod == other.wavelet.Lmethod; @@ -719,7 +723,6 @@ void ParamsEdited::initFrom (const std::vector wavelet.CHmethod = wavelet.CHmethod && p.wavelet.CHmethod == other.wavelet.CHmethod; wavelet.HSmethod = wavelet.HSmethod && p.wavelet.HSmethod == other.wavelet.HSmethod; wavelet.Dirmethod = wavelet.Dirmethod && p.wavelet.Dirmethod == other.wavelet.Dirmethod; - wavelet.tiles = wavelet.tiles && p.wavelet.tiles == other.wavelet.tiles; wavelet.rescon = wavelet.rescon && p.wavelet.rescon == other.wavelet.rescon; wavelet.resconH = wavelet.resconH && p.wavelet.resconH == other.wavelet.resconH; wavelet.reschro = wavelet.reschro && p.wavelet.reschro == other.wavelet.reschro; @@ -730,7 +733,10 @@ void ParamsEdited::initFrom (const std::vector wavelet.thres = wavelet.thres && p.wavelet.thres == other.wavelet.thres; wavelet.chroma = wavelet.chroma && p.wavelet.chroma == other.wavelet.chroma; wavelet.chro = wavelet.chro && p.wavelet.chro == other.wavelet.chro; - wavelet.unif = wavelet.unif && p.wavelet.unif == other.wavelet.unif; + wavelet.contrast = wavelet.contrast && p.wavelet.contrast == other.wavelet.contrast; + wavelet.edgrad = wavelet.edgrad && p.wavelet.edgrad == other.wavelet.edgrad; + wavelet.edgval = wavelet.edgval && p.wavelet.edgval == other.wavelet.edgval; + wavelet.edgthresh = wavelet.edgthresh && p.wavelet.edgthresh == other.wavelet.edgthresh; wavelet.thr = wavelet.thr && p.wavelet.thr == other.wavelet.thr; wavelet.thrH = wavelet.thrH && p.wavelet.thrH == other.wavelet.thrH; wavelet.hueskin = wavelet.hueskin && p.wavelet.hueskin == other.wavelet.hueskin; @@ -1091,6 +1097,7 @@ void ParamsEdited::combine (rtengine::procparams::ProcParams& toEdit, const rten if (raw.ff_AutoClipControl) toEdit.raw.ff_AutoClipControl = mods.raw.ff_AutoClipControl; if (raw.ff_clipControl) toEdit.raw.ff_clipControl = dontforceSet && options.baBehav[ADDSET_RAWFFCLIPCONTROL] ? toEdit.raw.ff_clipControl + mods.raw.ff_clipControl : mods.raw.ff_clipControl; if (wavelet.enabled) toEdit.wavelet.enabled = mods.wavelet.enabled; + if (wavelet.strength) toEdit.wavelet.strength = mods.wavelet.strength; if (wavelet.median) toEdit.wavelet.median = mods.wavelet.median; if (wavelet.avoid) toEdit.wavelet.avoid = mods.wavelet.avoid; if (wavelet.Lmethod) toEdit.wavelet.Lmethod = mods.wavelet.Lmethod; @@ -1099,6 +1106,7 @@ void ParamsEdited::combine (rtengine::procparams::ProcParams& toEdit, const rten if (wavelet.CHmethod) toEdit.wavelet.CHmethod = mods.wavelet.CHmethod; if (wavelet.HSmethod) toEdit.wavelet.HSmethod = mods.wavelet.HSmethod; if (wavelet.Dirmethod) toEdit.wavelet.Dirmethod = mods.wavelet.Dirmethod; + if (wavelet.edgthresh) toEdit.wavelet.edgthresh = mods.wavelet.edgthresh; if (wavelet.sky) toEdit.wavelet.sky= dontforceSet && options.baBehav[ADDSET_WA_SKYPROTECT] ? toEdit.wavelet.sky + mods.wavelet.sky : mods.wavelet.sky; if (wavelet.thr)toEdit.wavelet.thr= dontforceSet && options.baBehav[ADDSET_WA_THRR] ? toEdit.wavelet.thr + mods.wavelet.thr : mods.wavelet.thr; if (wavelet.thrH)toEdit.wavelet.thrH= dontforceSet && options.baBehav[ADDSET_WA_THRRH] ? toEdit.wavelet.thrH + mods.wavelet.thrH : mods.wavelet.thrH; @@ -1124,7 +1132,11 @@ void ParamsEdited::combine (rtengine::procparams::ProcParams& toEdit, const rten if (wavelet.threshold2)toEdit.wavelet.threshold2= dontforceSet && options.baBehav[ADDSET_WA_THRESHOLD2] ? toEdit.wavelet.threshold2 + mods.wavelet.threshold2 : mods.wavelet.threshold2; if (wavelet.chro)toEdit.wavelet.chro= dontforceSet && options.baBehav[ADDSET_WA_CHRO] ? toEdit.wavelet.chro + mods.wavelet.chro : mods.wavelet.chro; if (wavelet.chroma)toEdit.wavelet.chroma= dontforceSet && options.baBehav[ADDSET_WA_CHROMA] ? toEdit.wavelet.chroma + mods.wavelet.chroma : mods.wavelet.chroma; - if (wavelet.unif)toEdit.wavelet.unif= dontforceSet && options.baBehav[ADDSET_WA_UNIF] ? toEdit.wavelet.unif + mods.wavelet.unif : mods.wavelet.unif; + if (wavelet.contrast)toEdit.wavelet.contrast= dontforceSet && options.baBehav[ADDSET_WA_CONTRAST] ? toEdit.wavelet.contrast + mods.wavelet.contrast : mods.wavelet.contrast; + if (wavelet.edgrad)toEdit.wavelet.edgrad= dontforceSet && options.baBehav[ADDSET_WA_EDGRAD] ? toEdit.wavelet.edgrad + mods.wavelet.edgrad : mods.wavelet.edgrad; + if (wavelet.edgval)toEdit.wavelet.edgval= dontforceSet && options.baBehav[ADDSET_WA_EDGVAL] ? toEdit.wavelet.edgval + mods.wavelet.edgval : mods.wavelet.edgval; + if (wavelet.edgval)toEdit.wavelet.strength= dontforceSet && options.baBehav[ADDSET_WA_STRENGTH] ? toEdit.wavelet.strength + mods.wavelet.strength : mods.wavelet.strength; + if (dirpyrequalizer.enabled) toEdit.dirpyrequalizer.enabled = mods.dirpyrequalizer.enabled; if (dirpyrequalizer.gamutlab) toEdit.dirpyrequalizer.gamutlab = mods.dirpyrequalizer.gamutlab; diff --git a/rtgui/paramsedited.h b/rtgui/paramsedited.h index 07c387737..3d8fc3121 100644 --- a/rtgui/paramsedited.h +++ b/rtgui/paramsedited.h @@ -476,6 +476,7 @@ class WaveletParamsEdited { public: bool enabled; + bool strength; bool median; bool avoid; bool c[9]; @@ -485,7 +486,6 @@ class WaveletParamsEdited { bool CLmethod; bool Tilesmethod; bool Dirmethod; - bool tiles; bool rescon; bool resconH; bool reschro; @@ -496,7 +496,10 @@ class WaveletParamsEdited { bool threshold2; bool chroma; bool chro; - bool unif; + bool contrast; + bool edgrad; + bool edgval; + bool edgthresh; bool thr; bool thrH; bool skinprotect; diff --git a/rtgui/preferences.cc b/rtgui/preferences.cc index 4ce0b34e9..d887fafaf 100644 --- a/rtgui/preferences.cc +++ b/rtgui/preferences.cc @@ -307,14 +307,17 @@ Gtk::Widget* Preferences::getBatchProcPanel () { appendBehavList (mi, M("TP_WAVELET_THRESHOLD2"), ADDSET_WA_THRESHOLD2, true); appendBehavList (mi, M("TP_WAVELET_CHRO"), ADDSET_WA_CHRO, true); appendBehavList (mi, M("TP_WAVELET_CHR"), ADDSET_WA_CHROMA, true); - appendBehavList (mi, M("TP_WAVELET_SKIN"), ADDSET_WA_SKINPROTECT, true); + appendBehavList (mi, M("TP_WAVELET_SKIN"), ADDSET_WA_SKINPROTECT, true); + appendBehavList (mi, M("TP_WAVELET_EDRAD"), ADDSET_WA_EDGRAD, true); + appendBehavList (mi, M("TP_WAVELET_EDVAL"), ADDSET_WA_EDGVAL, true); appendBehavList (mi, M("TP_WAVELET_RESCON"), ADDSET_WA_RESCON, true); appendBehavList (mi, M("TP_WAVELET_THR"), ADDSET_WA_THRR, true); appendBehavList (mi, M("TP_WAVELET_RESCONH"), ADDSET_WA_RESCONH, true); appendBehavList (mi, M("TP_WAVELET_THRH"), ADDSET_WA_THRRH, true); appendBehavList (mi, M("TP_WAVELET_RESCHRO"), ADDSET_WA_RESCHRO, true); appendBehavList (mi, M("TP_WAVELET_SKY"), ADDSET_WA_SKYPROTECT, true); - appendBehavList (mi, M("TP_WAVELET_CONTRA"), ADDSET_WA_UNIF, true); + appendBehavList (mi, M("TP_WAVELET_CONTRA"), ADDSET_WA_CONTRAST, true); + appendBehavList (mi, M("TP_WAVELET_STRENGTH"), ADDSET_WA_STRENGTH, true); mi = behModel->append (); mi->set_value (behavColumns.label, M("TP_PREPROCESS_LABEL")); @@ -563,13 +566,11 @@ Gtk::Widget* Preferences::getPerformancePanel () { mainContainer->pack_start(*finspect, Gtk::PACK_SHRINK, 4); Gtk::Frame* fdenoise = Gtk::manage( new Gtk::Frame (M("PREFERENCES_NOISE")) ); - Gtk::VBox* vbdenoise = Gtk::manage( new Gtk::VBox () ); + Gtk::VBox* vbdenoise = Gtk::manage( new Gtk::VBox (Gtk::PACK_SHRINK, 4) ); vbdenoise->set_border_width (4); Gtk::Label* lreloadneeded2 = Gtk::manage (new Gtk::Label (M("PREFERENCES_IMG_RELOAD_NEEDED"), Gtk::ALIGN_LEFT)); - Gtk::HBox* threadLimitHB = Gtk::manage( new Gtk::HBox () ); - threadLimitHB->set_border_width(4); - threadLimitHB->set_spacing(4); + Gtk::HBox* threadLimitHB = Gtk::manage (new Gtk::HBox (Gtk::PACK_SHRINK, 4)); threadLimitHB->set_tooltip_text(M("PREFERENCES_RGBDTL_TOOLTIP")); Gtk::Label* RGBDTLl = Gtk::manage( new Gtk::Label (M("PREFERENCES_RGBDTL_LABEL") + ":", Gtk::ALIGN_LEFT)); rgbDenoiseTreadLimitSB = Gtk::manage( new Gtk::SpinButton () ); @@ -581,8 +582,8 @@ Gtk::Widget* Preferences::getPerformancePanel () { maxThreadNumber = omp_get_max_threads(); #endif rgbDenoiseTreadLimitSB->set_range (0, maxThreadNumber); - threadLimitHB->pack_start (*RGBDTLl, Gtk::PACK_SHRINK, 0); - threadLimitHB->pack_end (*rgbDenoiseTreadLimitSB, Gtk::PACK_SHRINK, 0); + threadLimitHB->pack_start (*RGBDTLl, Gtk::PACK_SHRINK, 2); + threadLimitHB->pack_end (*rgbDenoiseTreadLimitSB, Gtk::PACK_SHRINK, 2); Gtk::Label* dnlab = Gtk::manage (new Gtk::Label (M("PREFERENCES_LEVDN")+":", Gtk::ALIGN_LEFT)); Gtk::Label* dnautlab = Gtk::manage (new Gtk::Label (M("PREFERENCES_LEVAUTDN")+":", Gtk::ALIGN_LEFT)); @@ -633,9 +634,14 @@ Gtk::Widget* Preferences::getPerformancePanel () { colon->attach (*dnwavlab, 0, 1, 5, 6, Gtk::FILL, Gtk::SHRINK, 2, 2); colon->attach (*dnwavlev, 1, 2, 5, 6, Gtk::EXPAND | Gtk::FILL | Gtk::SHRINK, Gtk::SHRINK, 2, 2); - vbdenoise->pack_start (*lreloadneeded2, Gtk::PACK_SHRINK, 4); - vbdenoise->pack_start (*colon, Gtk::PACK_SHRINK, 4); - vbdenoise->pack_start(*threadLimitHB, Gtk::PACK_SHRINK, 4); + vbdenoise->pack_start (*lreloadneeded2, Gtk::PACK_SHRINK); + vbdenoise->pack_start (*colon, Gtk::PACK_SHRINK); + vbdenoise->pack_start(*threadLimitHB, Gtk::PACK_SHRINK); + // <--- To be hard-coded and removed once tested + cbdaubech = Gtk::manage (new Gtk::CheckButton (M("PREFERENCES_DAUB_LABEL"), Gtk::ALIGN_LEFT)); + cbdaubech->set_tooltip_markup (M("PREFERENCES_DAUB_TOOLTIP")); + vbdenoise->pack_start (*cbdaubech, Gtk::PACK_SHRINK); + // ---> fdenoise->add (*vbdenoise); mainContainer->pack_start (*fdenoise, Gtk::PACK_SHRINK, 4); @@ -1354,6 +1360,7 @@ void Preferences::storePreferences () { moptions.rtSettings.leveldnaut = dnaut->get_active_row_number (); moptions.rtSettings.nrwavlevel = dnwavlev->get_active_row_number (); moptions.rtSettings.leveldnautsimpl = dnautsimpl->get_active_row_number (); + moptions.rtSettings.daubech = cbdaubech->get_active (); moptions.prevdemo = (prevdemo_t)cprevdemo->get_active_row_number (); @@ -1465,6 +1472,7 @@ void Preferences::fillPreferences () { dnautsimpl->set_active (moptions.rtSettings.leveldnautsimpl); dnwavlev->set_active (moptions.rtSettings.nrwavlevel); cprevdemo->set_active (moptions.prevdemo); + cbdaubech->set_active (moptions.rtSettings.daubech); // cbAutocielab->set_active (moptions.rtSettings.autocielab); cbciecamfloat->set_active (moptions.rtSettings.ciecamfloat); diff --git a/rtgui/preferences.h b/rtgui/preferences.h index c450c2b66..7ecc5df6a 100644 --- a/rtgui/preferences.h +++ b/rtgui/preferences.h @@ -85,7 +85,7 @@ class Preferences : public Gtk::Dialog, public ProfileStoreListener { Gtk::CheckButton* cbAutoMonProfile; //Gtk::CheckButton* cbAutocielab; Gtk::CheckButton* cbciecamfloat; - + Gtk::CheckButton* cbdaubech; Gtk::SpinButton* hlThresh; Gtk::SpinButton* shThresh; @@ -102,6 +102,11 @@ class Preferences : public Gtk::Dialog, public ProfileStoreListener { Gtk::ComboBoxText* dnwavlev; Gtk::ComboBoxText* dnliss; + Gtk::Frame* waveletFrame; + Gtk::HBox* waveletTileSizeHBox; + Gtk::Label* waveletTileSizeLabel; + Gtk::ComboBoxText* waveletTileSizeCombo; + Gtk::ComboBoxText* cprevdemo; Gtk::ComboBoxText* theme; diff --git a/rtgui/wavelet.cc b/rtgui/wavelet.cc index 394ebea71..019025b98 100644 --- a/rtgui/wavelet.cc +++ b/rtgui/wavelet.cc @@ -57,20 +57,10 @@ Wavelet::Wavelet () : FoldableToolPanel(this) { enabled->set_active (true); pack_start(*enabled); enaConn = enabled->signal_toggled().connect( sigc::mem_fun(*this, &Wavelet::enabledToggled) ); + std::vector defaultCurve; - - // frame and expand - utilFrame = Gtk::manage (new Gtk::Frame () ); - exputil = Gtk::manage (new Gtk::Expander (M("TP_WAVELET_UTIL"))); - Gtk::HBox* hbutil = Gtk::manage( new Gtk::HBox()); - tbutil = Gtk::manage( new Gtk::ToggleButton()); - utilFrame->add(*exputil); - hbutil->set_spacing(8); - hbutil->pack_start(*tbutil); - tbutil->signal_toggled().connect( sigc::mem_fun(this, &Wavelet::exputilTog)); - dispFrame = Gtk::manage (new Gtk::Frame () ); expdisplay = Gtk::manage (new Gtk::Expander (M("TP_WAVELET_DISP"))); Gtk::HBox* hbdisplay = Gtk::manage( new Gtk::HBox()); @@ -106,6 +96,16 @@ Wavelet::Wavelet () : FoldableToolPanel(this) { hbtoning->set_spacing(8); hbtoning->pack_start(*tbtoning); tbtoning->signal_toggled().connect( sigc::mem_fun(this, &Wavelet::exptoningTog)); + + + edgeFrame = Gtk::manage (new Gtk::Frame () ); + expedge = Gtk::manage (new Gtk::Expander (M("TP_WAVELET_EDGE"))); + Gtk::HBox* hbedge = Gtk::manage( new Gtk::HBox()); + tbedge = Gtk::manage( new Gtk::ToggleButton()); + edgeFrame->add(*expedge); + hbedge->set_spacing(8); + hbedge->pack_start(*tbedge); +// tbtoning->signal_toggled().connect( sigc::mem_fun(this, &Wavelet::exptoningTog)); controlFrame = Gtk::manage (new Gtk::Frame () ); expgamut = Gtk::manage (new Gtk::Expander (M("TP_WAVELET_CONTR"))); @@ -133,49 +133,59 @@ Wavelet::Wavelet () : FoldableToolPanel(this) { // residualFrame->set_label_widget(*hbresid); // put the box as label for the frame. tbresid->signal_toggled().connect( sigc::mem_fun(this, &Wavelet::expresidTog)); //**************************************************** - - + + // Wavelet Settings + settingsFrame = Gtk::manage (new Gtk::Frame (M("TP_WAVELET_SETTINGS"))); + settingsVBox = Gtk::manage (new Gtk::VBox()); + settingsVBox->set_border_width(4); + settingsVBox->set_spacing(2); + + strength = Gtk::manage (new Adjuster (M("TP_WAVELET_STRENGTH"), 0, 100, 1, 100)); + strength->setAdjusterListener (this); + + thres = Gtk::manage (new Adjuster (M("TP_WAVELET_LEVELS"), 4, 9, 1, 7)); + thres->set_tooltip_text (M("TP_WAVELET_LEVELS_TOOLTIP")); + thres->setAdjusterListener (this); - // util... - Gtk::VBox * utiBox = Gtk::manage (new Gtk::VBox()); - utiBox->set_border_width(4); - utiBox->set_spacing(2); - - thres = Gtk::manage (new Adjuster (M("TP_WAVELET_THRES"), 4, 9, 1, 7)); - thres->set_tooltip_text (M("TP_WAVELET_THRES_TOOLTIP")); + tilesizeHBox = Gtk::manage (new Gtk::HBox()); + tilesizeLabel = Gtk::manage (new Gtk::Label (M("TP_WAVELET_TILESIZE") + ":")); Tilesmethod = Gtk::manage (new MyComboBoxText ()); Tilesmethod->append_text (M("TP_WAVELET_TILESFULL")); Tilesmethod->append_text (M("TP_WAVELET_TILESBIG")); Tilesmethod->append_text (M("TP_WAVELET_TILESLIT")); Tilesmethodconn = Tilesmethod->signal_changed().connect ( sigc::mem_fun(*this, &Wavelet::TilesmethodChanged) ); Tilesmethod->set_tooltip_text (M("TP_WAVELET_TILES_TOOLTIP")); - - //not use - tiles = Gtk::manage (new Adjuster (M("TP_WAVELET_TILES"), 12, 22, 1, 14)); - //tiles->set_tooltip_text (M("TP_WAVELET_TILES_TOOLTIP")); - thres->setAdjusterListener (this); - tiles->setAdjusterListener (this); - - utiBox->pack_start (*thres); - utiBox->pack_start (*Tilesmethod); + tilesizeHBox->pack_start(*tilesizeLabel, Gtk::PACK_SHRINK, 4); + tilesizeHBox->pack_start(*Tilesmethod); - //method for display levels + settingsVBox->pack_start(*strength); + settingsVBox->pack_start(*thres); + settingsVBox->pack_start(*tilesizeHBox); + settingsFrame->add(*settingsVBox); + pack_start (*settingsFrame, Gtk::PACK_EXPAND_WIDGET, 4); + + // Preview Settings Gtk::VBox * diBox = Gtk::manage (new Gtk::VBox()); diBox->set_border_width(4); diBox->set_spacing(2); + previewLevelsHBox = Gtk::manage (new Gtk::HBox()); + previewLevelsLabel = Gtk::manage (new Gtk::Label (M("TP_WAVELET_PREVIEWLEVELS") + ":")); + previewLevelsHBox->pack_start(*previewLevelsLabel, Gtk::PACK_SHRINK, 4); CLmethod = Gtk::manage (new MyComboBoxText ()); CLmethod->append_text (M("TP_WAVELET_ONE")); CLmethod->append_text (M("TP_WAVELET_INF")); CLmethod->append_text (M("TP_WAVELET_SUP")); CLmethod->append_text (M("TP_WAVELET_ALL")); CLmethodconn = CLmethod->signal_changed().connect ( sigc::mem_fun(*this, &Wavelet::CLmethodChanged) ); - diBox->pack_start (*CLmethod); + previewLevelsHBox->pack_start(*CLmethod); + diBox->pack_start (*previewLevelsHBox); + previewLDirHBox = Gtk::manage (new Gtk::HBox()); Lmethod = Gtk::manage (new MyComboBoxText ()); - Lmethod->append_text (M("TP_WAVELET_0")); + Lmethod->set_sensitive(false); Lmethod->append_text (M("TP_WAVELET_1")); Lmethod->append_text (M("TP_WAVELET_2")); Lmethod->append_text (M("TP_WAVELET_3")); @@ -184,20 +194,25 @@ Wavelet::Wavelet () : FoldableToolPanel(this) { Lmethod->append_text (M("TP_WAVELET_6")); Lmethod->append_text (M("TP_WAVELET_7")); Lmethod->append_text (M("TP_WAVELET_8")); + Lmethod->append_text (M("TP_WAVELET_9")); + Lmethod->append_text (M("TP_WAVELET_SUPE")); + Lmethod->append_text (M("TP_WAVELET_RESID")); Lmethod->set_active(0); Lmethodconn = Lmethod->signal_changed().connect ( sigc::mem_fun(*this, &Wavelet::LmethodChanged) ); - diBox->pack_start (*Lmethod); - Dirmethod = Gtk::manage (new MyComboBoxText ()); + Dirmethod->set_sensitive(false); Dirmethod->append_text (M("TP_WAVELET_DONE")); Dirmethod->append_text (M("TP_WAVELET_DTWO")); Dirmethod->append_text (M("TP_WAVELET_DTHR")); Dirmethod->append_text (M("TP_WAVELET_DALL")); Dirmethodconn = Dirmethod->signal_changed().connect ( sigc::mem_fun(*this, &Wavelet::DirmethodChanged) ); - diBox->pack_start (*Dirmethod); - + previewLDirHBox->pack_start(*Lmethod, Gtk::PACK_EXPAND_WIDGET, 2); + previewLDirHBox->pack_start(*Dirmethod); + + diBox->pack_start (*previewLDirHBox, Gtk::PACK_EXPAND_WIDGET, 0); + // residual image Gtk::VBox * resBox = Gtk::manage (new Gtk::VBox()); resBox->set_border_width(4); @@ -223,11 +238,11 @@ Wavelet::Wavelet () : FoldableToolPanel(this) { thrH->setAdjusterListener (this); - unif = Gtk::manage (new Adjuster (M("TP_WAVELET_CONTRA"), -100, 100, 1, 0)); - unif->set_tooltip_text (M("TP_WAVELET_CONTRA_TOOLTIP")); + contrast = Gtk::manage (new Adjuster (M("TP_WAVELET_CONTRA"), -100, 100, 1, 0)); + contrast->set_tooltip_text (M("TP_WAVELET_CONTRA_TOOLTIP")); - resBox->pack_start(*unif); //keep the possibility to reinstall - unif->setAdjusterListener (this); + resBox->pack_start(*contrast); //keep the possibility to reinstall + contrast->setAdjusterListener (this); reschro = Gtk::manage (new Adjuster (M("TP_WAVELET_RESCHRO"), -100, 100, 1, 0)); @@ -292,18 +307,18 @@ Wavelet::Wavelet () : FoldableToolPanel(this) { Glib::ustring ss; switch( i ){ case 0: - ss =Glib::ustring::compose( "%1 (%2)",i, M("TP_WAVELET_FINEST"));break; + ss =Glib::ustring::compose( "%1 (%2)",(i+1), M("TP_WAVELET_FINEST"));break; case 8: - ss =Glib::ustring::compose( "%1 (%2)",i, M("TP_WAVELET_LARGEST"));break; + ss =Glib::ustring::compose( "%1 (%2)",(i+1), M("TP_WAVELET_LARGEST"));break; default: - ss =Glib::ustring::compose( "%1",i); + ss =Glib::ustring::compose( "%1",(i+1)); } - correction[i] = Gtk::manage ( new Adjuster (ss, -100, 150, 1, 0) ); + correction[i] = Gtk::manage ( new Adjuster (ss, -100, 250, 1, 0) ); correction[i]->setAdjusterListener(this); levBox->pack_start(*correction[i]); } - sup = Gtk::manage (new Adjuster (M("TP_WAVELET_SUPE"), -100, 150, 1, 0)); + sup = Gtk::manage (new Adjuster (M("TP_WAVELET_SUPE"), -100, 250, 1, 0)); levBox->pack_start(*sup); sup->setAdjusterListener (this); wavLabels->show(); @@ -314,34 +329,40 @@ Wavelet::Wavelet () : FoldableToolPanel(this) { levBox->pack_start(*separatorC, Gtk::PACK_SHRINK, 2); + contrastSHFrame = Gtk::manage (new Gtk::Frame (M("TP_WAVELET_APPLYTO"))); + contrastSHVBox = Gtk::manage (new Gtk::VBox); + contrastSHVBox->set_border_width(4); + contrastSHVBox->set_spacing(2); + HSmethod = Gtk::manage (new MyComboBoxText ()); HSmethod->append_text (M("TP_WAVELET_HS1")); HSmethod->append_text (M("TP_WAVELET_HS2")); HSmethodconn = HSmethod->signal_changed().connect ( sigc::mem_fun(*this, &Wavelet::HSmethodChanged) ); - levBox->pack_start(*HSmethod); - - - hllev = Gtk::manage (new ThresholdAdjuster (M("TP_WAVELET_HIGHLIGHT"), 0., 100., 50., 75., 100., 98., 0, false)); + hllev = Gtk::manage (new ThresholdAdjuster (M("TP_WAVELET_HIGHLIGHT"), 0., 100., 50., 75., 100., 98., 0, false)); hllev->setAdjusterListener (this); hllev->setBgGradient(milestones2); - levBox->pack_start(*hllev); threshold = Gtk::manage (new Adjuster (M("TP_WAVELET_THRESHOLD"), 1, 9, 1, 5)); - levBox->pack_start(*threshold); threshold->setAdjusterListener (this); threshold->set_tooltip_text (M("TP_WAVELET_THRESHOLD_TOOLTIP")); bllev = Gtk::manage (new ThresholdAdjuster (M("TP_WAVELET_LOWLIGHT"), 0., 100., 0., 2., 50., 25., 0, false)); bllev->setAdjusterListener (this); bllev->setBgGradient(milestones2); - levBox->pack_start(*bllev); threshold2 = Gtk::manage (new Adjuster (M("TP_WAVELET_THRESHOLD2"), 1, 9, 1, 4)); - levBox->pack_start(*threshold2); threshold2->setAdjusterListener (this); threshold2->set_tooltip_text (M("TP_WAVELET_THRESHOLD2_TOOLTIP")); + contrastSHVBox->pack_start(*HSmethod); //remove 2? + contrastSHVBox->pack_start(*hllev); + contrastSHVBox->pack_start(*threshold); + contrastSHVBox->pack_start(*bllev); + contrastSHVBox->pack_start(*threshold2); + contrastSHFrame->add(*contrastSHVBox); + levBox->pack_start(*contrastSHFrame); + // chroma lev Gtk::VBox * chBox = Gtk::manage (new Gtk::VBox()); chBox->set_border_width(4); @@ -430,8 +451,24 @@ Wavelet::Wavelet () : FoldableToolPanel(this) { tonBox->pack_start( *opacityCurveEditorG, Gtk::PACK_SHRINK, 2); + //----------- Edge------------------------------ + Gtk::VBox * edgBox = Gtk::manage (new Gtk::VBox()); + edgBox->set_border_width(4); + edgBox->set_spacing(2); + edgrad = Gtk::manage ( new Adjuster (M("TP_WAVELET_EDRAD"), 0, 100, 1, 15) ); + edgrad->setAdjusterListener(this); + edgBox->pack_start(*edgrad); + //->set_tooltip_markup (M("TP_WAVELET_SKIN_TOOLTIP")); + edgval = Gtk::manage ( new Adjuster (M("TP_WAVELET_EDVAL"), 0, 100, 1, 0) ); + edgval->setAdjusterListener(this); + edgBox->pack_start(*edgval); + + //not use + edgthresh = Gtk::manage (new Adjuster (M("TP_WAVELET_EDGTHRESH"), 0, 100, 1, 10 )); + edgthresh->setAdjusterListener (this); + edgBox->pack_start (*edgthresh); // gamut control------------------------------------------------- Gtk::VBox * conBox = Gtk::manage (new Gtk::VBox()); @@ -460,12 +497,9 @@ Wavelet::Wavelet () : FoldableToolPanel(this) { avoidConn = avoid->signal_toggled().connect( sigc::mem_fun(*this, &Wavelet::avoidToggled) ); conBox->pack_start(*avoid); //************************** - exputil->add(*utiBox); - pack_start (*utilFrame, Gtk::PACK_EXPAND_WIDGET, 4); - - expdisplay->add(*diBox); - pack_start (*dispFrame, Gtk::PACK_EXPAND_WIDGET, 4); - + expdisplay->add(*diBox); + pack_start (*dispFrame, Gtk::PACK_EXPAND_WIDGET, 4); + expcontrast->add(*levBox); pack_start (*levelFrame, Gtk::PACK_EXPAND_WIDGET, 4); @@ -474,6 +508,9 @@ Wavelet::Wavelet () : FoldableToolPanel(this) { exptoning->add(*tonBox); pack_start (*toningFrame, Gtk::PACK_EXPAND_WIDGET, 4); + + expedge->add(*edgBox); + pack_start (*edgeFrame, Gtk::PACK_EXPAND_WIDGET, 4); expgamut->add(*conBox); pack_start (*controlFrame, Gtk::PACK_EXPAND_WIDGET, 4); @@ -547,14 +584,18 @@ void Wavelet::read (const ProcParams* pp, const ParamsEdited* pedited) { CHmethodChanged(); CLmethod->set_active (3); - if (pp->wavelet.CLmethod=="one") + if (pp->wavelet.CLmethod=="one") { CLmethod->set_active (0); - else if (pp->wavelet.CLmethod=="inf") + } + else if (pp->wavelet.CLmethod=="inf") { CLmethod->set_active (1); - else if (pp->wavelet.CLmethod=="sup") + } + else if (pp->wavelet.CLmethod=="sup") { CLmethod->set_active (2); - else if (pp->wavelet.CLmethod=="all") + } + else if (pp->wavelet.CLmethod=="all") { CLmethod->set_active (3); + } CLmethodChanged(); Tilesmethod->set_active (2); @@ -576,27 +617,10 @@ void Wavelet::read (const ProcParams* pp, const ParamsEdited* pedited) { else if (pp->wavelet.Dirmethod=="all") Dirmethod->set_active (3); DirmethodChanged(); - - Lmethod->set_active (4); - if (pp->wavelet.Lmethod=="0_") - Lmethod->set_active (0); - else if (pp->wavelet.Lmethod=="1_") - Lmethod->set_active (1); - else if (pp->wavelet.Lmethod=="2_") - Lmethod->set_active (2); - else if (pp->wavelet.Lmethod=="3_") - Lmethod->set_active (3); - else if (pp->wavelet.Lmethod=="4_") - Lmethod->set_active (4); - else if (pp->wavelet.Lmethod=="5_") - Lmethod->set_active (5); - else if (pp->wavelet.Lmethod=="6_") - Lmethod->set_active (6); - else if (pp->wavelet.Lmethod=="7_") - Lmethod->set_active (7); - else if (pp->wavelet.Lmethod=="8_") - Lmethod->set_active (8); - + + int selectedLevel = atoi(pp->wavelet.Lmethod.data())-1; + Lmethod->set_active (selectedLevel == -1 ? 4 :selectedLevel); + LmethodChanged(); if (pedited) { @@ -618,7 +642,7 @@ void Wavelet::read (const ProcParams* pp, const ParamsEdited* pedited) { opacityShapeRG->setCurve (pp->wavelet.opacityCurveRG); opacityShapeBY->setCurve (pp->wavelet.opacityCurveBY); avoid->set_inconsistent (!pedited->wavelet.avoid); - tiles->setEditedState (pedited->wavelet.tiles ? Edited : UnEdited); + edgthresh->setEditedState (pedited->wavelet.edgthresh ? Edited : UnEdited); rescon->setEditedState (pedited->wavelet.rescon ? Edited : UnEdited); resconH->setEditedState (pedited->wavelet.resconH ? Edited : UnEdited); reschro->setEditedState (pedited->wavelet.reschro ? Edited : UnEdited); @@ -630,7 +654,9 @@ void Wavelet::read (const ProcParams* pp, const ParamsEdited* pedited) { chroma->setEditedState (pedited->wavelet.chroma ? Edited : UnEdited); chro->setEditedState (pedited->wavelet.chro ? Edited : UnEdited); median->set_inconsistent (!pedited->wavelet.median); - unif->setEditedState (pedited->wavelet.unif ? Edited : UnEdited); + contrast->setEditedState (pedited->wavelet.contrast ? Edited : UnEdited); + edgrad->setEditedState (pedited->wavelet.edgrad ? Edited : UnEdited); + edgval->setEditedState (pedited->wavelet.edgval ? Edited : UnEdited); thr->setEditedState (pedited->wavelet.thr ? Edited : UnEdited); thrH->setEditedState (pedited->wavelet.thrH ? Edited : UnEdited); skinprotect->setEditedState (pedited->wavelet.skinprotect ? Edited : UnEdited); @@ -644,6 +670,7 @@ void Wavelet::read (const ProcParams* pp, const ParamsEdited* pedited) { for(int i = 0; i < 9; i++) { correction[i]->setEditedState (pedited->wavelet.c[i] ? Edited : UnEdited); } + strength->setEditedState(pedited->wavelet.strength ? Edited : UnEdited); } ccshape->setCurve (pp->wavelet.clvcurve); opacityShapeRG->setCurve (pp->wavelet.opacityCurveRG); @@ -661,7 +688,6 @@ void Wavelet::read (const ProcParams* pp, const ParamsEdited* pedited) { lastmedian = pp->wavelet.median; lastEnabled = pp->wavelet.enabled; lastavoid = pp->wavelet.avoid; - tiles->setValue (pp->wavelet.tiles); rescon->setValue (pp->wavelet.rescon); resconH->setValue (pp->wavelet.resconH); reschro->setValue (pp->wavelet.reschro); @@ -670,7 +696,10 @@ void Wavelet::read (const ProcParams* pp, const ParamsEdited* pedited) { thres->setValue (pp->wavelet.thres); chroma->setValue (pp->wavelet.chroma); chro->setValue (pp->wavelet.chro); - unif->setValue (pp->wavelet.unif); + contrast->setValue (pp->wavelet.contrast); + edgrad->setValue (pp->wavelet.edgrad); + edgval->setValue (pp->wavelet.edgval); + edgthresh->setValue (pp->wavelet.edgthresh); thr->setValue (pp->wavelet.thr); thrH->setValue (pp->wavelet.thrH); skinprotect->setValue(pp->wavelet.skinprotect); @@ -685,6 +714,7 @@ void Wavelet::read (const ProcParams* pp, const ParamsEdited* pedited) { for (int i = 0; i < 9; i++) { correction[i]->setValue(pp->wavelet.c[i]); } + strength->setValue(pp->wavelet.strength); int y; y=thres->getValue(); int z; @@ -715,7 +745,6 @@ void Wavelet::write (ProcParams* pp, ParamsEdited* pedited) { pp->wavelet.enabled = enabled->get_active (); pp->wavelet.avoid = avoid->get_active (); - pp->wavelet.tiles = tiles->getValue(); pp->wavelet.rescon = rescon->getValue(); pp->wavelet.resconH = resconH->getValue(); pp->wavelet.reschro = reschro->getValue(); @@ -725,7 +754,10 @@ void Wavelet::write (ProcParams* pp, ParamsEdited* pedited) { pp->wavelet.chroma = chroma->getValue(); pp->wavelet.chro = chro->getValue(); pp->wavelet.median = median->get_active (); - pp->wavelet.unif = unif->getValue(); + pp->wavelet.contrast = contrast->getValue(); + pp->wavelet.edgrad = edgrad->getValue(); + pp->wavelet.edgval = edgval->getValue(); + pp->wavelet.edgthresh = edgthresh->getValue(); pp->wavelet.thr = thr->getValue(); pp->wavelet.thrH = thrH->getValue(); pp->wavelet.hueskin = hueskin->getValue (); @@ -744,7 +776,7 @@ void Wavelet::write (ProcParams* pp, ParamsEdited* pedited) { for (int i = 0; i < 9; i++) { pp->wavelet.c[i] = (int) correction[i]->getValue(); } - + pp->wavelet.strength = (int) strength->getValue(); if (pedited) { pedited->wavelet.enabled = !enabled->get_inconsistent(); pedited->wavelet.avoid = !avoid->get_inconsistent(); @@ -755,7 +787,7 @@ void Wavelet::write (ProcParams* pp, ParamsEdited* pedited) { pedited->wavelet.CHmethod = CHmethod->get_active_row_number() != 2; pedited->wavelet.HSmethod = HSmethod->get_active_row_number() != 1; pedited->wavelet.Dirmethod = Dirmethod->get_active_row_number() != 3; - pedited->wavelet.tiles = tiles->getEditedState(); + pedited->wavelet.edgthresh = edgthresh->getEditedState(); pedited->wavelet.rescon = rescon->getEditedState(); pedited->wavelet.resconH = resconH->getEditedState(); pedited->wavelet.reschro = reschro->getEditedState(); @@ -766,7 +798,9 @@ void Wavelet::write (ProcParams* pp, ParamsEdited* pedited) { pedited->wavelet.threshold2 = threshold2->getEditedState(); pedited->wavelet.chroma = chroma->getEditedState(); pedited->wavelet.chro = chro->getEditedState(); - pedited->wavelet.unif = unif->getEditedState(); + pedited->wavelet.contrast = contrast->getEditedState(); + pedited->wavelet.edgrad = edgrad->getEditedState(); + pedited->wavelet.edgval = edgval->getEditedState(); pedited->wavelet.thr = thr->getEditedState(); pedited->wavelet.thrH = thrH->getEditedState(); pedited->wavelet.hueskin = hueskin->getEditedState (); @@ -783,6 +817,7 @@ void Wavelet::write (ProcParams* pp, ParamsEdited* pedited) { for(int i = 0; i < 9; i++) { pedited->wavelet.c[i] = correction[i]->getEditedState(); } + pedited->wavelet.strength = strength->getEditedState (); } if (CHmethod->get_active_row_number()==0) pp->wavelet.CHmethod = "without"; @@ -821,25 +856,29 @@ void Wavelet::write (ProcParams* pp, ParamsEdited* pedited) { else if (Dirmethod->get_active_row_number()==3) pp->wavelet.Dirmethod = "all"; + char lMethod[3]; // one additional char to avoid buffer overrun if someone increases number of levels > 9 + sprintf(lMethod, "%d", Lmethod->get_active_row_number()+1); + pp->wavelet.Lmethod = lMethod; +/* if (Lmethod->get_active_row_number()==0) - pp->wavelet.Lmethod = "0_"; - else if (Lmethod->get_active_row_number()==1) pp->wavelet.Lmethod = "1_"; - else if (Lmethod->get_active_row_number()==2) + else if (Lmethod->get_active_row_number()==1) pp->wavelet.Lmethod = "2_"; - else if (Lmethod->get_active_row_number()==3) + else if (Lmethod->get_active_row_number()==2) pp->wavelet.Lmethod = "3_"; - else if (Lmethod->get_active_row_number()==4) + else if (Lmethod->get_active_row_number()==3) pp->wavelet.Lmethod = "4_"; - else if (Lmethod->get_active_row_number()==5) + else if (Lmethod->get_active_row_number()==4) pp->wavelet.Lmethod = "5_"; - else if (Lmethod->get_active_row_number()==6) + else if (Lmethod->get_active_row_number()==5) pp->wavelet.Lmethod = "6_"; - else if (Lmethod->get_active_row_number()==7) + else if (Lmethod->get_active_row_number()==6) pp->wavelet.Lmethod = "7_"; - else if (Lmethod->get_active_row_number()==8) + else if (Lmethod->get_active_row_number()==7) pp->wavelet.Lmethod = "8_"; - + else if (Lmethod->get_active_row_number()==8) + pp->wavelet.Lmethod = "9_"; +*/ } @@ -860,7 +899,7 @@ void Wavelet::setDefaults (const ProcParams* defParams, const ParamsEdited* pedi for (int i = 0; i < 9; i++) { correction[i]->setDefault(defParams->wavelet.c[i]); } - tiles->setDefault (defParams->wavelet.tiles); + strength->setDefault(defParams->wavelet.strength ); rescon->setDefault (defParams->wavelet.rescon); resconH->setDefault (defParams->wavelet.resconH); reschro->setDefault (defParams->wavelet.reschro); @@ -871,7 +910,10 @@ void Wavelet::setDefaults (const ProcParams* defParams, const ParamsEdited* pedi threshold2->setDefault (defParams->wavelet.threshold2); chroma->setDefault (defParams->wavelet.chroma); chro->setDefault (defParams->wavelet.chro); - unif->setDefault (defParams->wavelet.unif); + contrast->setDefault (defParams->wavelet.contrast); + edgrad->setDefault (defParams->wavelet.edgrad); + edgval->setDefault (defParams->wavelet.edgval); + edgthresh->setDefault (defParams->wavelet.edgthresh); thr->setDefault (defParams->wavelet.thr); thrH->setDefault (defParams->wavelet.thrH); hueskin->setDefault (defParams->wavelet.hueskin); @@ -882,7 +924,6 @@ void Wavelet::setDefaults (const ProcParams* defParams, const ParamsEdited* pedi satlev->setDefault (defParams->wavelet.satlev); if (pedited) { - tiles->setDefault (defParams->wavelet.tiles); rescon->setDefault (defParams->wavelet.rescon); resconH->setDefault (defParams->wavelet.resconH); reschro->setDefault (defParams->wavelet.reschro); @@ -893,7 +934,10 @@ void Wavelet::setDefaults (const ProcParams* defParams, const ParamsEdited* pedi threshold2->setDefaultEditedState(pedited->wavelet.threshold2 ? Edited : UnEdited); chroma->setDefaultEditedState(pedited->wavelet.chroma ? Edited : UnEdited); chro->setDefaultEditedState(pedited->wavelet.chro ? Edited : UnEdited); - unif->setDefaultEditedState(pedited->wavelet.unif ? Edited : UnEdited); + contrast->setDefaultEditedState(pedited->wavelet.contrast ? Edited : UnEdited); + edgrad->setDefaultEditedState(pedited->wavelet.edgrad ? Edited : UnEdited); + edgval->setDefaultEditedState(pedited->wavelet.edgval ? Edited : UnEdited); + edgthresh->setDefault (defParams->wavelet.edgthresh); thr->setDefaultEditedState(pedited->wavelet.thr ? Edited : UnEdited); thrH->setDefaultEditedState(pedited->wavelet.thrH ? Edited : UnEdited); skinprotect->setDefaultEditedState(pedited->wavelet.skinprotect ? Edited : UnEdited); @@ -904,12 +948,12 @@ void Wavelet::setDefaults (const ProcParams* defParams, const ParamsEdited* pedi pastlev->setDefaultEditedState (pedited->wavelet.pastlev ? Edited : UnEdited); satlev->setDefaultEditedState (pedited->wavelet.satlev ? Edited : UnEdited); - for (int i = 0; i < 9; i++) { - correction[i]->setDefaultEditedState(pedited->wavelet.c[i] ? Edited : UnEdited); - } + for (int i = 0; i < 9; i++) { + correction[i]->setDefaultEditedState(pedited->wavelet.c[i] ? Edited : UnEdited); + } + strength->setDefaultEditedState (pedited->wavelet.strength ? Edited : UnEdited); } else { - tiles->setDefaultEditedState(Irrelevant); rescon->setDefaultEditedState(Irrelevant); resconH->setDefaultEditedState(Irrelevant); reschro->setDefaultEditedState(Irrelevant); @@ -920,7 +964,10 @@ void Wavelet::setDefaults (const ProcParams* defParams, const ParamsEdited* pedi threshold2->setDefaultEditedState(Irrelevant); chroma->setDefaultEditedState(Irrelevant); chro->setDefaultEditedState(Irrelevant); - unif->setDefaultEditedState(Irrelevant); + contrast->setDefaultEditedState(Irrelevant); + edgrad->setDefaultEditedState(Irrelevant); + edgval->setDefaultEditedState(Irrelevant); + edgthresh->setDefaultEditedState(Irrelevant); thr->setDefaultEditedState(Irrelevant); thrH->setDefaultEditedState(Irrelevant); skinprotect->setDefaultEditedState(Irrelevant); @@ -934,6 +981,8 @@ void Wavelet::setDefaults (const ProcParams* defParams, const ParamsEdited* pedi for (int i = 0; i < 9; i++) { correction[i]->setDefaultEditedState(Irrelevant); } + strength->setDefaultEditedState (Irrelevant); + } } @@ -1018,6 +1067,26 @@ void Wavelet::CLmethodChanged() { if (listener && (multiImage||enabled->get_active()) ) { listener->panelChanged (EvWavCLmet, CLmethod->get_active_text ()); } + if (CLmethod->get_active_row_number()==0) { + CLmethod->set_active (0); + Lmethod->set_sensitive(true); + Dirmethod->set_sensitive(true); + } + else if (CLmethod->get_active_row_number()==1) { + CLmethod->set_active (1); + Lmethod->set_sensitive(true); + Dirmethod->set_sensitive(true); + } + else if (CLmethod->get_active_row_number()==2) { + CLmethod->set_active (2); + Lmethod->set_sensitive(true); + Dirmethod->set_sensitive(true); + } + else if (CLmethod->get_active_row_number()==3) { + CLmethod->set_active (3); + Lmethod->set_sensitive(false); + Dirmethod->set_sensitive(false); + } } void Wavelet::TilesmethodChanged() { @@ -1054,7 +1123,6 @@ void Wavelet::setBatchMode (bool batchMode) { CLVcurveEditorG->setBatchMode (batchMode); opaCurveEditorG->setBatchMode (batchMode); opacityCurveEditorG->setBatchMode (batchMode); - tiles->showEditedCB (); rescon->showEditedCB (); resconH->showEditedCB (); reschro->showEditedCB (); @@ -1065,7 +1133,10 @@ void Wavelet::setBatchMode (bool batchMode) { threshold2->showEditedCB (); chroma->showEditedCB (); chro->showEditedCB (); - unif->showEditedCB (); + contrast->showEditedCB (); + edgrad->showEditedCB (); + edgval->showEditedCB (); + edgthresh->showEditedCB (); thr->showEditedCB (); thrH->showEditedCB (); skinprotect->showEditedCB(); @@ -1080,14 +1151,15 @@ void Wavelet::setBatchMode (bool batchMode) { for (int i = 0; i < 9; i++) { correction[i]->showEditedCB(); } + strength->showEditedCB (); } void Wavelet::adjusterChanged (Adjuster* a, double newval) { if (listener && enabled->get_active()) { - if (a == tiles) { + if (a == edgthresh) { listener->panelChanged (EvWavtiles, Glib::ustring::compose("%1", - Glib::ustring::format(std::fixed, std::setprecision(0), tiles->getValue())) + Glib::ustring::format(std::fixed, std::setprecision(0), edgthresh->getValue())) ); } else if (a == rescon ) { @@ -1135,10 +1207,10 @@ void Wavelet::adjusterChanged (Adjuster* a, double newval) { Glib::ustring::format(std::fixed, std::setprecision(0), chro->getValue())) ); } - else if (a == unif ) { + else if (a == contrast ) { listener->panelChanged (EvWavunif, Glib::ustring::compose("%1", - Glib::ustring::format(std::fixed, std::setprecision(0), unif->getValue())) + Glib::ustring::format(std::fixed, std::setprecision(0), contrast->getValue())) ); } else if (a == thr ) { @@ -1165,6 +1237,18 @@ void Wavelet::adjusterChanged (Adjuster* a, double newval) { Glib::ustring::format(std::fixed, std::setprecision(0), threshold2->getValue())) ); } + else if (a == edgrad ) { + listener->panelChanged (EvWavedgrad, + Glib::ustring::compose("%1", + Glib::ustring::format(std::fixed, std::setprecision(0), edgrad->getValue())) + ); + } + else if (a == edgval ) { + listener->panelChanged (EvWavedgval, + Glib::ustring::compose("%1", + Glib::ustring::format(std::fixed, std::setprecision(0), edgval->getValue())) + ); + } else if (a == thres ) { int y; @@ -1187,6 +1271,13 @@ void Wavelet::adjusterChanged (Adjuster* a, double newval) { Glib::ustring::format(std::fixed, std::setprecision(2), skinprotect->getValue())) ); } + + else if (a == strength) { + listener->panelChanged (EvWavStrength, + Glib::ustring::compose("%1", + Glib::ustring::format(std::fixed, std::setprecision(2), strength->getValue())) + ); + } else { @@ -1278,14 +1369,6 @@ void Wavelet::expgamutTog () { controlFrame->hide(); } } -void Wavelet::exputilTog () { - if (tbutil->get_active ()) { - utilFrame->show(); - } - else { - utilFrame->hide(); - } -} void Wavelet::expdisplayTog () { if (tbdisplay->get_active ()) { dispFrame->show(); @@ -1385,7 +1468,7 @@ void Wavelet::colorForValue (double valX, double valY, enum ColorCaller::ElemTyp caller->ccGreen = double(G); caller->ccBlue = double(B); } -void Wavelet::setAdjusterBehavior (bool multiplieradd, bool thresholdadd, bool threshold2add, bool thresadd, bool chroadd,bool chromaadd, bool unifadd, bool skinadd, bool reschroadd, bool resconadd, bool resconHadd, bool thradd, bool thrHadd, bool skyadd ) { +void Wavelet::setAdjusterBehavior (bool multiplieradd, bool thresholdadd, bool threshold2add, bool thresadd, bool chroadd,bool chromaadd, bool contrastadd, bool skinadd, bool reschroadd, bool resconadd, bool resconHadd, bool thradd, bool thrHadd, bool skyadd, bool edgradadd, bool edgvaladd, bool strengthadd ) { for (int i=0; i<9; i++) correction[i]->setAddMode(multiplieradd); @@ -1395,13 +1478,17 @@ void Wavelet::setAdjusterBehavior (bool multiplieradd, bool thresholdadd, bool t thres->setAddMode(thresadd); chro->setAddMode(chroadd); chroma->setAddMode(chromaadd); - unif->setAddMode(unifadd); + contrast->setAddMode(contrastadd); rescon->setAddMode(resconadd); resconH->setAddMode(resconHadd); reschro->setAddMode(reschroadd); thr->setAddMode(thradd); thrH->setAddMode(thrHadd); - sky->setAddMode(skyadd); + sky->setAddMode(skyadd); + edgrad->setAddMode(edgradadd); + edgval->setAddMode(edgvaladd); + strength->setAddMode(strengthadd); + } diff --git a/rtgui/wavelet.h b/rtgui/wavelet.h index 582ebad4d..78dd4a617 100644 --- a/rtgui/wavelet.h +++ b/rtgui/wavelet.h @@ -59,13 +59,12 @@ protected: Gtk::ToggleButton * tbgamut; Gtk::ToggleButton * tbchroma; Gtk::ToggleButton * tbtoning; - Gtk::ToggleButton * tbutil; Gtk::ToggleButton * tbdisplay; + Gtk::ToggleButton * tbedge; Gtk::CheckButton * cbresid; Gtk::Image* igRes; Adjuster* correction[9]; - Adjuster* tiles; Adjuster* rescon; Adjuster* resconH; Adjuster* reschro; @@ -74,10 +73,15 @@ protected: Adjuster* thres; Adjuster* chroma; Adjuster* chro; - Adjuster* unif; + Adjuster* contrast; Adjuster* thr; Adjuster* thrH; Adjuster* skinprotect; + Adjuster* edgrad; + Adjuster* edgval; + Adjuster* edgthresh; + Adjuster* strength; + ThresholdAdjuster* hueskin; ThresholdAdjuster* hueskin2; ThresholdAdjuster* hllev; @@ -98,24 +102,35 @@ protected: sigc::connection Tilesmethodconn; MyComboBoxText* Dirmethod; sigc::connection Dirmethodconn; + Gtk::Frame* settingsFrame; Gtk::Frame* toningFrame; Gtk::Frame* residualFrame; - Gtk::Frame* utilFrame; Gtk::Frame* dispFrame; Gtk::Frame* levelFrame; Gtk::Frame* chromaFrame; Gtk::Frame* controlFrame; + Gtk::Frame* edgeFrame; + Gtk::Frame* contrastSHFrame; Gtk::Label* colLabel; Gtk::Label* interLabel; - Gtk::Label* wavLabels; + Gtk::Label* wavLabels; + Gtk::Label* hsmethodLabel; Gtk::Expander* expcontrast; Gtk::Expander* expresid; Gtk::Expander* expgamut; Gtk::Expander* expchroma; Gtk::Expander* exptoning; - Gtk::Expander* exputil; Gtk::Expander* expdisplay; + Gtk::Expander* expedge; Gtk::HBox* hbresid; + Gtk::HBox* tilesizeHBox; + Gtk::HBox* previewLevelsHBox; + Gtk::HBox* previewLDirHBox; + Gtk::HBox* hsmethodHBox; + Gtk::VBox* settingsVBox; + Gtk::VBox* contrastSHVBox; + Gtk::Label* tilesizeLabel; + Gtk::Label* previewLevelsLabel; sigc::connection enaConn, expConn, medianConn, avoidConn; sigc::connection neutralPressedConn; @@ -148,7 +163,7 @@ public: void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited=NULL); void setBatchMode (bool batchMode); void adjusterChanged2 (ThresholdAdjuster* a, int newBottomL, int newTopL, int newBottomR, int newTopR); - void setAdjusterBehavior (bool multiplieradd, bool thresholdadd, bool threshold2add, bool thresadd, bool chroadd,bool chromaadd, bool unifadd, bool skinadd, bool reschroadd, bool resconadd, bool resconHadd, bool thradd, bool thrHadd, bool skyadd); + void setAdjusterBehavior (bool multiplieradd, bool thresholdadd, bool threshold2add, bool thresadd, bool chroadd,bool chromaadd, bool contrastadd, bool skinadd, bool reschroadd, bool resconadd, bool resconHadd, bool thradd, bool thrHadd, bool skyadd, bool edgradadd, bool edgvaladd, bool strengthadd); void adjusterChanged (Adjuster* a, double newval); void enabledToggled (); @@ -157,7 +172,6 @@ public: void expresidTog (); void expdisplayTog (); void expgamutTog (); - void exputilTog (); void expchromaTog (); void exptoningTog (); void avoidToggled ();