From fce2d61b0cf58064e333041a7e9e9099d83b6090 Mon Sep 17 00:00:00 2001 From: Alberto Griggio Date: Tue, 24 Jul 2018 17:00:54 +0200 Subject: [PATCH 01/42] moved softlight later in the pipeline Gives a better result, more suitable to the final fine-tuning --- rtengine/dcrop.cc | 2 ++ rtengine/improccoordinator.cc | 3 +- rtengine/improcfun.cc | 2 +- rtengine/improcfun.h | 2 +- rtengine/ipsoftlight.cc | 63 ++++++++++++++++++----------------- rtengine/rtthumbnail.cc | 2 ++ rtengine/simpleprocess.cc | 2 ++ rtgui/softlight.cc | 4 +-- 8 files changed, 44 insertions(+), 36 deletions(-) diff --git a/rtengine/dcrop.cc b/rtengine/dcrop.cc index 3b1ebfdab..731eca086 100644 --- a/rtengine/dcrop.cc +++ b/rtengine/dcrop.cc @@ -1011,6 +1011,8 @@ void Crop::update(int todo) parent->ipf.ip_wavelet(labnCrop, labnCrop, kall, WaveParams, wavCLVCurve, waOpacityCurveRG, waOpacityCurveBY, waOpacityCurveW, waOpacityCurveWL, parent->wavclCurve, skip); } + parent->ipf.softLight(labnCrop); + // } // } diff --git a/rtengine/improccoordinator.cc b/rtengine/improccoordinator.cc index 832d193a2..84c315ac4 100644 --- a/rtengine/improccoordinator.cc +++ b/rtengine/improccoordinator.cc @@ -782,7 +782,8 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange) } - + ipf.softLight(nprevl); + if (params.colorappearance.enabled) { //L histo and Chroma histo for ciecam // histogram well be for Lab (Lch) values, because very difficult to do with J,Q, M, s, C diff --git a/rtengine/improcfun.cc b/rtengine/improcfun.cc index 7d9d080e2..57475af9c 100644 --- a/rtengine/improcfun.cc +++ b/rtengine/improcfun.cc @@ -3186,7 +3186,7 @@ void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, PipetteBuffer } } - softLight(rtemp, gtemp, btemp, istart, jstart, tW, tH, TS); + //softLight(rtemp, gtemp, btemp, istart, jstart, tW, tH, TS); if (!blackwhite) { if (editImgFloat || editWhatever) { diff --git a/rtengine/improcfun.h b/rtengine/improcfun.h index a97ecef40..066d1e306 100644 --- a/rtengine/improcfun.h +++ b/rtengine/improcfun.h @@ -343,7 +343,7 @@ public: void localContrast(LabImage *lab); void colorToningLabGrid(LabImage *lab, int xstart, int xend, int ystart, int yend, bool MultiThread); void shadowsHighlights(LabImage *lab); - void softLight(float *red, float *green, float *blue, int istart, int jstart, int tW, int tH, int TS); + void softLight(LabImage *lab); Image8* lab2rgb(LabImage* lab, int cx, int cy, int cw, int ch, const procparams::ColorManagementParams &icm, bool consider_histogram_settings = true); Imagefloat* lab2rgbOut(LabImage* lab, int cx, int cy, int cw, int ch, const procparams::ColorManagementParams &icm); diff --git a/rtengine/ipsoftlight.cc b/rtengine/ipsoftlight.cc index 35bf9577a..74fb543aa 100644 --- a/rtengine/ipsoftlight.cc +++ b/rtengine/ipsoftlight.cc @@ -26,48 +26,49 @@ namespace rtengine { -void ImProcFunctions::softLight(float *red, float *green, float *blue, int istart, int jstart, int tW, int tH, int TS) +namespace { + +inline float sl(float blend, float x) +{ + if (!OOG(x)) { + const float orig = 1.f - blend; + float v = Color::gamma_srgb(x) / MAXVALF; + // Pegtop's formula from + // https://en.wikipedia.org/wiki/Blend_modes#Soft_Light + float v2 = v * v; + float v22 = v2 * 2.f; + v = v2 + v22 - v22 * v; + x = blend * Color::igamma_srgb(v * MAXVALF) + orig * x; + } + return x; +} + +} // namespace + + +void ImProcFunctions::softLight(LabImage *lab) { if (!params->softlight.enabled || !params->softlight.strength) { return; } + Imagefloat working(lab->W, lab->H); + lab2rgb(*lab, working, params->icm.workingProfile); + const float blend = params->softlight.strength / 100.f; - const float orig = 1.f - blend; - - const auto apply = - [=](float x) -> float - { - if (!OOG(x)) { - float v = Color::gamma_srgb(x) / MAXVALF; - // Pegtop's formula from - // https://en.wikipedia.org/wiki/Blend_modes#Soft_Light - float v2 = v * v; - float v22 = v2 * 2.f; - v = v2 + v22 - v22 * v; - x = blend * Color::igamma_srgb(v * MAXVALF) + orig * x; - } - return x; - }; #ifdef _OPENMP - #pragma omp parallel if (multiThread) + #pragma omp parallel for #endif - { - int ti = 0; -#ifdef _OPENMP - #pragma omp for -#endif - for (int i = istart; i < tH; i++) { - for (int j = jstart, tj = 0; j < tW; j++, tj++) { - const int idx = ti * TS + tj; - red[idx] = apply(red[idx]); - green[idx] = apply(green[idx]); - blue[idx] = apply(blue[idx]); - } - ++ti; + for (int y = 0; y < working.getHeight(); ++y) { + for (int x = 0; x < working.getWidth(); ++x) { + working.r(y, x) = sl(blend, working.r(y, x)); + working.g(y, x) = sl(blend, working.g(y, x)); + working.b(y, x) = sl(blend, working.b(y, x)); } } + + rgb2lab(working, *lab, params->icm.workingProfile); } } // namespace rtengine diff --git a/rtengine/rtthumbnail.cc b/rtengine/rtthumbnail.cc index 79dee36bf..afd8836a1 100644 --- a/rtengine/rtthumbnail.cc +++ b/rtengine/rtthumbnail.cc @@ -1368,6 +1368,8 @@ IImage8* Thumbnail::processImage (const procparams::ProcParams& params, eSensorT ipf.EPDToneMap (labView, 5, 6); } + ipf.softLight(labView); + if (params.colorappearance.enabled) { CurveFactory::curveLightBrightColor ( params.colorappearance.curve, diff --git a/rtengine/simpleprocess.cc b/rtengine/simpleprocess.cc index fbee20f44..b74c11d32 100644 --- a/rtengine/simpleprocess.cc +++ b/rtengine/simpleprocess.cc @@ -1133,6 +1133,8 @@ private: wavCLVCurve.Reset(); + ipf.softLight(labView); + //Colorappearance and tone-mapping associated int f_w = 1, f_h = 1; diff --git a/rtgui/softlight.cc b/rtgui/softlight.cc index 0ee4c64b9..072c45e98 100644 --- a/rtgui/softlight.cc +++ b/rtgui/softlight.cc @@ -28,8 +28,8 @@ using namespace rtengine::procparams; SoftLight::SoftLight(): FoldableToolPanel(this, "softlight", M("TP_SOFTLIGHT_LABEL"), false, true) { auto m = ProcEventMapper::getInstance(); - EvSoftLightEnabled = m->newEvent(RGBCURVE, "HISTORY_MSG_SOFTLIGHT_ENABLED"); - EvSoftLightStrength = m->newEvent(RGBCURVE, "HISTORY_MSG_SOFTLIGHT_STRENGTH"); + EvSoftLightEnabled = m->newEvent(LUMINANCECURVE, "HISTORY_MSG_SOFTLIGHT_ENABLED"); + EvSoftLightStrength = m->newEvent(LUMINANCECURVE, "HISTORY_MSG_SOFTLIGHT_STRENGTH"); strength = Gtk::manage(new Adjuster(M("TP_SOFTLIGHT_STRENGTH"), 0., 100., 1., 30.)); strength->setAdjusterListener(this); From 14ac4babec51e1c4e2cb2e3d09542e5afc5d583c Mon Sep 17 00:00:00 2001 From: Alberto Griggio Date: Wed, 10 Oct 2018 10:02:06 +0200 Subject: [PATCH 02/42] added haze removal tool Based on the paper: "Single Image Haze Removal Using Dark Channel Prior" by He, Sun and Tang using a guided filter for the "soft matting" of the transmission map --- rtdata/languages/default | 35 ++-- rtengine/CMakeLists.txt | 1 + rtengine/color.h | 4 + rtengine/dcrop.cc | 3 +- rtengine/improccoordinator.cc | 3 +- rtengine/improcfun.h | 1 + rtengine/ipdehaze.cc | 335 ++++++++++++++++++++++++++++++++++ rtengine/procparams.cc | 31 ++++ rtengine/procparams.h | 12 ++ rtengine/rtthumbnail.cc | 1 + rtengine/simpleprocess.cc | 1 + rtengine/tmo_fattal02.cc | 2 +- rtgui/CMakeLists.txt | 1 + rtgui/addsetids.h | 1 + rtgui/batchtoolpanelcoord.cc | 2 + rtgui/dehaze.cc | 115 ++++++++++++ rtgui/dehaze.h | 47 +++++ rtgui/paramsedited.cc | 12 ++ rtgui/paramsedited.h | 9 + rtgui/partialpastedlg.cc | 9 + rtgui/partialpastedlg.h | 3 +- rtgui/preferences.cc | 4 + rtgui/toolpanelcoord.cc | 2 + rtgui/toolpanelcoord.h | 2 + 24 files changed, 617 insertions(+), 19 deletions(-) create mode 100644 rtengine/ipdehaze.cc create mode 100644 rtgui/dehaze.cc create mode 100644 rtgui/dehaze.h diff --git a/rtdata/languages/default b/rtdata/languages/default index 963659884..dcf626948 100644 --- a/rtdata/languages/default +++ b/rtdata/languages/default @@ -398,7 +398,7 @@ HISTORY_MSG_145;Microcontrast - Uniformity HISTORY_MSG_146;Edge sharpening HISTORY_MSG_147;ES - Luminance only HISTORY_MSG_148;Microcontrast -HISTORY_MSG_149;Microcontrast - 3×3 matrix +HISTORY_MSG_149;Microcontrast - 33 matrix HISTORY_MSG_150;Post-demosaic artifact/noise red. HISTORY_MSG_151;Vibrance HISTORY_MSG_152;Vib - Pastel tones @@ -728,6 +728,8 @@ HISTORY_MSG_492;RGB Curves HISTORY_MSG_493;L*a*b* Adjustments HISTORY_MSG_CLAMPOOG;Clip out-of-gamut colors HISTORY_MSG_COLORTONING_LABGRID_VALUE;CT - Color correction +HISTORY_MSG_DEHAZE_ENABLED;Haze Removal +HISTORY_MSG_DEHAZE_STRENGTH;Dehaze - Strength HISTORY_MSG_DUALDEMOSAIC_CONTRAST;AMaZE+VNG4 - Contrast threshold HISTORY_MSG_HISTMATCHING;Auto-matched tone curve HISTORY_MSG_ICM_OUTPUT_PRIMARIES;Output - Primaries @@ -807,7 +809,7 @@ IPTCPANEL_CITY;City IPTCPANEL_CITYHINT;Enter the name of the city pictured in this image. IPTCPANEL_COPYHINT;Copy IPTC settings to clipboard. IPTCPANEL_COPYRIGHT;Copyright notice -IPTCPANEL_COPYRIGHTHINT;Enter a Notice on the current owner of the Copyright for this image, such as ©2008 Jane Doe. +IPTCPANEL_COPYRIGHTHINT;Enter a Notice on the current owner of the Copyright for this image, such as 2008 Jane Doe. IPTCPANEL_COUNTRY;Country IPTCPANEL_COUNTRYHINT;Enter the name of the country pictured in this image. IPTCPANEL_CREATOR;Creator @@ -954,6 +956,7 @@ PARTIALPASTE_CROP;Crop PARTIALPASTE_DARKFRAMEAUTOSELECT;Dark-frame auto-selection PARTIALPASTE_DARKFRAMEFILE;Dark-frame file PARTIALPASTE_DEFRINGE;Defringe +PARTIALPASTE_DEHAZE;Haze removal PARTIALPASTE_DETAILGROUP;Detail Settings PARTIALPASTE_DIALOGLABEL;Partial paste processing profile PARTIALPASTE_DIRPYRDENOISE;Noise reduction @@ -1366,9 +1369,9 @@ TP_COARSETRAF_TOOLTIP_ROTLEFT;Rotate left.\n\nShortcuts:\n[ - Multiple Ed TP_COARSETRAF_TOOLTIP_ROTRIGHT;Rotate right.\n\nShortcuts:\n] - Multiple Editor Tabs Mode,\nAlt-] - Single Editor Tab Mode. TP_COARSETRAF_TOOLTIP_VFLIP;Flip vertically. TP_COLORAPP_ADAPTSCENE;Scene absolute luminance -TP_COLORAPP_ADAPTSCENE_TOOLTIP;Absolute luminance of the scene environment (cd/m²).\n1) Calculated from the Exif data:\nShutter speed - ISO speed - F number - camera exposure correction.\n2) Calculated from the raw white point and RT's Exposure Compensation slider. -TP_COLORAPP_ADAPTVIEWING;Viewing absolute luminance (cd/m²) -TP_COLORAPP_ADAPTVIEWING_TOOLTIP;Absolute luminance of the viewing environment\n(usually 16cd/m²). +TP_COLORAPP_ADAPTSCENE_TOOLTIP;Absolute luminance of the scene environment (cd/m).\n1) Calculated from the Exif data:\nShutter speed - ISO speed - F number - camera exposure correction.\n2) Calculated from the raw white point and RT's Exposure Compensation slider. +TP_COLORAPP_ADAPTVIEWING;Viewing absolute luminance (cd/m) +TP_COLORAPP_ADAPTVIEWING_TOOLTIP;Absolute luminance of the viewing environment\n(usually 16cd/m). TP_COLORAPP_ADAP_AUTO_TOOLTIP;If the checkbox is checked (recommended) RawTherapee calculates an optimum value from the Exif data.\nTo set the value manually, uncheck the checkbox first. TP_COLORAPP_ALGO;Algorithm TP_COLORAPP_ALGO_ALL;All @@ -1405,7 +1408,7 @@ TP_COLORAPP_FREE;Free temp+green + CAT02 + [output] TP_COLORAPP_GAMUT;Gamut control (L*a*b*) TP_COLORAPP_GAMUT_TOOLTIP;Allow gamut control in L*a*b* mode. TP_COLORAPP_HUE;Hue (h) -TP_COLORAPP_HUE_TOOLTIP;Hue (h) - angle between 0° and 360°. +TP_COLORAPP_HUE_TOOLTIP;Hue (h) - angle between 0 and 360. TP_COLORAPP_LABEL;CIE Color Appearance Model 2002 TP_COLORAPP_LABEL_CAM02;Image Adjustments TP_COLORAPP_LABEL_SCENE;Scene Conditions @@ -1505,6 +1508,8 @@ TP_DARKFRAME_LABEL;Dark-Frame TP_DEFRINGE_LABEL;Defringe TP_DEFRINGE_RADIUS;Radius TP_DEFRINGE_THRESHOLD;Threshold +TP_DEHAZE_LABEL;Haze Removal +TP_DEHAZE_STRENGTH;Strength TP_DIRPYRDENOISE_CHROMINANCE_AMZ;Auto multi-zones TP_DIRPYRDENOISE_CHROMINANCE_AUTOGLOBAL;Automatic global TP_DIRPYRDENOISE_CHROMINANCE_AUTOGLOBAL_TOOLTIP;Try to evaluate chroma noise\nBe careful, this calculation is average, and is quite subjective ! @@ -1552,16 +1557,16 @@ TP_DIRPYRDENOISE_MEDIAN_METHOD_RGB;RGB TP_DIRPYRDENOISE_MEDIAN_METHOD_TOOLTIP;When using the "Luminance only" and "L*a*b*" methods, median filtering will be performed just after the wavelet step in the noise reduction pipeline.\nWhen using the "RGB" mode, it will be performed at the very end of the noise reduction pipeline. TP_DIRPYRDENOISE_MEDIAN_METHOD_WEIGHTED;Weighted L* (little) + a*b* (normal) TP_DIRPYRDENOISE_MEDIAN_PASSES;Median iterations -TP_DIRPYRDENOISE_MEDIAN_PASSES_TOOLTIP;Applying three median filter iterations with a 3×3 window size often leads to better results than using one median filter iteration with a 7×7 window size. +TP_DIRPYRDENOISE_MEDIAN_PASSES_TOOLTIP;Applying three median filter iterations with a 33 window size often leads to better results than using one median filter iteration with a 77 window size. TP_DIRPYRDENOISE_MEDIAN_TYPE;Median type -TP_DIRPYRDENOISE_MEDIAN_TYPE_TOOLTIP;Apply a median filter of the desired window size. The larger the window's size, the longer it takes.\n\n3×3 soft: treats 5 pixels in a 3×3 pixel window.\n3×3: treats 9 pixels in a 3×3 pixel window.\n5×5 soft: treats 13 pixels in a 5×5 pixel window.\n5×5: treats 25 pixels in a 5×5 pixel window.\n7×7: treats 49 pixels in a 7×7 pixel window.\n9×9: treats 81 pixels in a 9×9 pixel window.\n\nSometimes it is possible to achieve higher quality running several iterations with a smaller window size than one iteration with a larger one. +TP_DIRPYRDENOISE_MEDIAN_TYPE_TOOLTIP;Apply a median filter of the desired window size. The larger the window's size, the longer it takes.\n\n33 soft: treats 5 pixels in a 33 pixel window.\n33: treats 9 pixels in a 33 pixel window.\n55 soft: treats 13 pixels in a 55 pixel window.\n55: treats 25 pixels in a 55 pixel window.\n77: treats 49 pixels in a 77 pixel window.\n99: treats 81 pixels in a 99 pixel window.\n\nSometimes it is possible to achieve higher quality running several iterations with a smaller window size than one iteration with a larger one. TP_DIRPYRDENOISE_SLI;Slider -TP_DIRPYRDENOISE_TYPE_3X3;3×3 -TP_DIRPYRDENOISE_TYPE_3X3SOFT;3×3 soft -TP_DIRPYRDENOISE_TYPE_5X5;5×5 -TP_DIRPYRDENOISE_TYPE_5X5SOFT;5×5 soft -TP_DIRPYRDENOISE_TYPE_7X7;7×7 -TP_DIRPYRDENOISE_TYPE_9X9;9×9 +TP_DIRPYRDENOISE_TYPE_3X3;33 +TP_DIRPYRDENOISE_TYPE_3X3SOFT;33 soft +TP_DIRPYRDENOISE_TYPE_5X5;55 +TP_DIRPYRDENOISE_TYPE_5X5SOFT;55 soft +TP_DIRPYRDENOISE_TYPE_7X7;77 +TP_DIRPYRDENOISE_TYPE_9X9;99 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_ARTIF;Reduce artifacts @@ -2005,7 +2010,7 @@ TP_SHARPENING_USM;Unsharp Mask TP_SHARPENMICRO_AMOUNT;Quantity TP_SHARPENMICRO_CONTRAST;Contrast threshold TP_SHARPENMICRO_LABEL;Microcontrast -TP_SHARPENMICRO_MATRIX;3×3 matrix instead of 5×5 +TP_SHARPENMICRO_MATRIX;33 matrix instead of 55 TP_SHARPENMICRO_UNIFORMITY;Uniformity TP_SOFTLIGHT_LABEL;Soft Light TP_SOFTLIGHT_STRENGTH;Strength diff --git a/rtengine/CMakeLists.txt b/rtengine/CMakeLists.txt index 759316e33..f610cc8b0 100644 --- a/rtengine/CMakeLists.txt +++ b/rtengine/CMakeLists.txt @@ -128,6 +128,7 @@ set(RTENGINESOURCEFILES vng4_demosaic_RT.cc ipsoftlight.cc guidedfilter.cc + ipdehaze.cc ) if(LENSFUN_HAS_LOAD_DIRECTORY) diff --git a/rtengine/color.h b/rtengine/color.h index 1e6eef578..b6459adc4 100644 --- a/rtengine/color.h +++ b/rtengine/color.h @@ -205,6 +205,10 @@ public: return r * 0.2126729 + g * 0.7151521 + b * 0.0721750; } + static float rgbLuminance(float r, float g, float b, const double workingspace[3][3]) + { + return r * workingspace[1][0] + g * workingspace[1][1] + b * workingspace[1][2]; + } /** * @brief Convert red/green/blue to L*a*b diff --git a/rtengine/dcrop.cc b/rtengine/dcrop.cc index 002747070..d72b7389c 100644 --- a/rtengine/dcrop.cc +++ b/rtengine/dcrop.cc @@ -692,7 +692,7 @@ void Crop::update(int todo) std::unique_ptr fattalCrop; - if ((todo & M_HDR) && params.fattal.enabled) { + if ((todo & M_HDR) && (params.fattal.enabled || params.dehaze.enabled)) { Imagefloat *f = origCrop; int fw = skips(parent->fw, skip); int fh = skips(parent->fh, skip); @@ -741,6 +741,7 @@ void Crop::update(int todo) } if (need_fattal) { + parent->ipf.dehaze(f); parent->ipf.ToneMapFattal02(f); } diff --git a/rtengine/improccoordinator.cc b/rtengine/improccoordinator.cc index 298c3fc58..dec7fef91 100644 --- a/rtengine/improccoordinator.cc +++ b/rtengine/improccoordinator.cc @@ -413,12 +413,13 @@ void ImProcCoordinator::updatePreviewImage(int todo, Crop* cropCall) readyphase++; - if ((todo & M_HDR) && params.fattal.enabled) { + if ((todo & M_HDR) && (params.fattal.enabled || params.dehaze.enabled)) { if (fattal_11_dcrop_cache) { delete fattal_11_dcrop_cache; fattal_11_dcrop_cache = nullptr; } + ipf.dehaze(orig_prev); ipf.ToneMapFattal02(orig_prev); if (oprevi != orig_prev) { diff --git a/rtengine/improcfun.h b/rtengine/improcfun.h index a97ecef40..216641a45 100644 --- a/rtengine/improcfun.h +++ b/rtengine/improcfun.h @@ -339,6 +339,7 @@ public: void Badpixelscam(CieImage * ncie, double radius, int thresh, int mode, float chrom, bool hotbad); void BadpixelsLab(LabImage * lab, double radius, int thresh, float chrom); + void dehaze(Imagefloat *rgb); void ToneMapFattal02(Imagefloat *rgb); void localContrast(LabImage *lab); void colorToningLabGrid(LabImage *lab, int xstart, int xend, int ystart, int yend, bool MultiThread); diff --git a/rtengine/ipdehaze.cc b/rtengine/ipdehaze.cc new file mode 100644 index 000000000..aed647417 --- /dev/null +++ b/rtengine/ipdehaze.cc @@ -0,0 +1,335 @@ +/* -*- C++ -*- + * + * This file is part of RawTherapee. + * + * Copyright (c) 2018 Alberto Griggio + * + * RawTherapee is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * RawTherapee is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with RawTherapee. If not, see . + */ + +/* + * Haze removal using the algorithm described in the paper: + * + * Single Image Haze Removal Using Dark Channel Prior + * by He, Sun and Tang + * + * using a guided filter for the "soft matting" of the transmission map + * + */ + +#include "improcfun.h" +#include "guidedfilter.h" +#include "rt_math.h" +#include "rt_algo.h" +#include +#include + +extern Options options; + +namespace rtengine { + +namespace { + +#if 0 +# define DEBUG_DUMP(arr) \ + do { \ + Imagefloat im(arr.width(), arr.height()); \ + const char *out = "/tmp/" #arr ".tif"; \ + for (int y = 0; y < im.getHeight(); ++y) { \ + for (int x = 0; x < im.getWidth(); ++x) { \ + im.r(y, x) = im.g(y, x) = im.b(y, x) = arr[y][x] * 65535.f; \ + } \ + } \ + im.saveTIFF(out, 16); \ + } while (false) +#else +# define DEBUG_DUMP(arr) +#endif + + +int get_dark_channel(const Imagefloat &src, array2D &dst, + int patchsize, float *ambient, bool multithread) +{ + const int w = src.getWidth(); + const int h = src.getHeight(); + + int npatches = 0; + +#ifdef _OPENMP + #pragma omp parallel for if (multithread) +#endif + for (int y = 0; y < src.getHeight(); y += patchsize) { + int pH = std::min(y+patchsize, h); + for (int x = 0; x < src.getWidth(); x += patchsize, ++npatches) { + float val = RT_INFINITY_F; + int pW = std::min(x+patchsize, w); + for (int yy = y; yy < pH; ++yy) { + float yval = RT_INFINITY_F; + for (int xx = x; xx < pW; ++xx) { + float r = src.r(yy, xx); + float g = src.g(yy, xx); + float b = src.b(yy, xx); + if (ambient) { + r /= ambient[0]; + g /= ambient[1]; + b /= ambient[2]; + } + yval = min(yval, r, g, b); + } + val = min(val, yval); + } + for (int yy = y; yy < pH; ++yy) { + std::fill(dst[yy]+x, dst[yy]+pW, val); + } + for (int yy = y; yy < pH; ++yy) { + for (int xx = x; xx < pW; ++xx) { + float r = src.r(yy, xx); + float g = src.g(yy, xx); + float b = src.b(yy, xx); + if (ambient) { + r /= ambient[0]; + g /= ambient[1]; + b /= ambient[2]; + } + float l = min(r, g, b); + if (l >= 2.f * val) { + dst[yy][xx] = l; + } + } + } + } + } + + return npatches; +} + + +int estimate_ambient_light(const Imagefloat *img, const array2D &dark, const array2D &Y, int patchsize, int npatches, float ambient[3]) +{ + const int W = img->getWidth(); + const int H = img->getHeight(); + + const auto get_percentile = + [](std::priority_queue &q, float prcnt) -> float + { + size_t n = LIM(q.size() * prcnt, 1, q.size()); + while (q.size() > n) { + q.pop(); + } + return q.top(); + }; + + float lim = RT_INFINITY_F; + { + std::priority_queue p; + for (int y = 0; y < H; y += patchsize) { + for (int x = 0; x < W; x += patchsize) { + p.push(dark[y][x]); + } + } + lim = get_percentile(p, 0.95); + } + + std::vector> patches; + patches.reserve(npatches); + + for (int y = 0; y < H; y += patchsize) { + for (int x = 0; x < W; x += patchsize) { + if (dark[y][x] >= lim) { + patches.push_back(std::make_pair(x, y)); + } + } + } + + if (options.rtSettings.verbose) { + std::cout << "dehaze: computing ambient light from " << patches.size() + << " patches" << std::endl; + } + + { + std::priority_queue l; + + for (auto &p : patches) { + const int pW = std::min(p.first+patchsize, W); + const int pH = std::min(p.second+patchsize, H); + + for (int y = p.second; y < pH; ++y) { + for (int x = p.first; x < pW; ++x) { + l.push(Y[y][x]); + } + } + } + + lim = get_percentile(l, 0.95); + } + + double rr = 0, gg = 0, bb = 0; + int n = 0; + for (auto &p : patches) { + const int pW = std::min(p.first+patchsize, W); + const int pH = std::min(p.second+patchsize, H); + + for (int y = p.second; y < pH; ++y) { + for (int x = p.first; x < pW; ++x) { + if (Y[y][x] >= lim) { + float r = img->r(y, x); + float g = img->g(y, x); + float b = img->b(y, x); + rr += r; + gg += g; + bb += b; + ++n; + } + } + } + } + ambient[0] = rr / n; + ambient[1] = gg / n; + ambient[2] = bb / n; + + return n; +} + + +void get_luminance(Imagefloat *img, array2D &Y, TMatrix ws, bool multithread) +{ + const int W = img->getWidth(); + const int H = img->getHeight(); + +#ifdef _OPENMP + #pragma omp parallel for if (multithread) +#endif + for (int y = 0; y < H; ++y) { + for (int x = 0; x < W; ++x) { + Y[y][x] = Color::rgbLuminance(img->r(y, x), img->g(y, x), img->b(y, x), ws); + } + } +} + + +} // namespace + + +void ImProcFunctions::dehaze(Imagefloat *img) +{ + if (!params->dehaze.enabled) { + return; + } + + img->normalizeFloatTo1(); + + const int W = img->getWidth(); + const int H = img->getHeight(); + const float strength = LIM01(float(params->dehaze.strength) / 100.f * 0.9f); + + if (options.rtSettings.verbose) { + std::cout << "dehaze: strength = " << strength << std::endl; + } + + array2D dark(W, H); + const int patchsize = std::max(W / 200, 2); + int npatches = get_dark_channel(*img, dark, patchsize, nullptr, multiThread); + DEBUG_DUMP(dark); + + TMatrix ws = ICCStore::getInstance()->workingSpaceMatrix(params->icm.workingProfile); + array2D Y(W, H); + get_luminance(img, Y, ws, multiThread); + + float ambient[3]; + int n = estimate_ambient_light(img, dark, Y, patchsize, npatches, ambient); + float ambient_Y = Color::rgbLuminance(ambient[0], ambient[1], ambient[2], ws); + + if (options.rtSettings.verbose) { + std::cout << "dehaze: ambient light is " + << ambient[0] << ", " << ambient[1] << ", " << ambient[2] + << " (average of " << n << ")" + << std::endl; + std::cout << " ambient luminance is " << ambient_Y << std::endl; + } + + if (min(ambient[0], ambient[1], ambient[2]) < 0.01f) { + if (options.rtSettings.verbose) { + std::cout << "dehaze: no haze detected" << std::endl; + } + img->normalizeFloatTo65535(); + return; // probably no haze at all + } + + array2D &t_tilde = dark; + get_dark_channel(*img, dark, patchsize, ambient, multiThread); + DEBUG_DUMP(t_tilde); + +#ifdef _OPENMP + #pragma omp parallel for if (multiThread) +#endif + for (int y = 0; y < H; ++y) { + for (int x = 0; x < W; ++x) { + dark[y][x] = 1.f - strength * dark[y][x]; + } + } + + const int radius = patchsize * 2; + const float epsilon = 2.5e-4; + array2D &t = t_tilde; + + guidedFilter(Y, t_tilde, t, radius, epsilon, multiThread); + + DEBUG_DUMP(t); + + const float t0 = 0.01; +#ifdef _OPENMP + #pragma omp parallel for if (multiThread) +#endif + for (int y = 0; y < H; ++y) { + for (int x = 0; x < W; ++x) { + float mt = std::max(t[y][x], t0); + float r = (img->r(y, x) - ambient[0]) / mt + ambient[0]; + float g = (img->g(y, x) - ambient[1]) / mt + ambient[1]; + float b = (img->b(y, x) - ambient[2]) / mt + ambient[2]; + img->r(y, x) = r; + img->g(y, x) = g; + img->b(y, x) = b; + } + } + + float oldmed; + findMinMaxPercentile(Y, Y.width() * Y.height(), 0.5, oldmed, 0.5, oldmed, multiThread); + + get_luminance(img, Y, ws, multiThread); + float newmed; + + findMinMaxPercentile(Y, Y.width() * Y.height(), 0.5, newmed, 0.5, newmed, multiThread); + + if (newmed > 1e-5f) { + const float f1 = oldmed / newmed; + const float f = f1 * 65535.f; +#ifdef _OPENMP + #pragma omp parallel for if (multiThread) +#endif + for (int y = 0; y < H; ++y) { + for (int x = 0; x < W; ++x) { + float r = img->r(y, x); + float g = img->g(y, x); + float b = img->b(y, x); + float h, s, l; + Color::rgb2hslfloat(r * f, g * f, b * f, h, s, l); + s = LIM01(s / f1); + Color::hsl2rgbfloat(h, s, l, img->r(y, x), img->g(y, x), img->b(y, x)); + } + } + } +} + + +} // namespace rtengine diff --git a/rtengine/procparams.cc b/rtengine/procparams.cc index 4d0c7aed0..ceace7c3b 100644 --- a/rtengine/procparams.cc +++ b/rtengine/procparams.cc @@ -2373,6 +2373,26 @@ bool SoftLightParams::operator !=(const SoftLightParams& other) const return !(*this == other); } + +DehazeParams::DehazeParams() : + enabled(false), + strength(50) +{ +} + +bool DehazeParams::operator ==(const DehazeParams& other) const +{ + return + enabled == other.enabled + && strength == other.strength; +} + +bool DehazeParams::operator !=(const DehazeParams& other) const +{ + return !(*this == other); +} + + RAWParams::BayerSensor::BayerSensor() : method(getMethodString(Method::AMAZE)), border(4), @@ -2727,6 +2747,8 @@ void ProcParams::setDefaults() softlight = SoftLightParams(); + dehaze = DehazeParams(); + raw = RAWParams(); metadata = MetaDataParams(); @@ -3037,6 +3059,10 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo saveToKeyfile(!pedited || pedited->defringe.threshold, "Defringing", "Threshold", defringe.threshold, keyFile); saveToKeyfile(!pedited || pedited->defringe.huecurve, "Defringing", "HueCurve", defringe.huecurve, keyFile); +// Dehaze + saveToKeyfile(!pedited || pedited->dehaze.enabled, "Dehaze", "Enabled", dehaze.enabled, keyFile); + saveToKeyfile(!pedited || pedited->dehaze.strength, "Dehaze", "Strength", dehaze.strength, keyFile); + // Directional pyramid denoising saveToKeyfile(!pedited || pedited->dirpyrDenoise.enabled, "Directional Pyramid Denoising", "Enabled", dirpyrDenoise.enabled, keyFile); saveToKeyfile(!pedited || pedited->dirpyrDenoise.enhance, "Directional Pyramid Denoising", "Enhance", dirpyrDenoise.enhance, keyFile); @@ -4618,6 +4644,11 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited) assignFromKeyfile(keyFile, "SoftLight", "Strength", pedited, softlight.strength, pedited->softlight.strength); } + if (keyFile.has_group("Dehaze")) { + assignFromKeyfile(keyFile, "Dehaze", "Enabled", pedited, dehaze.enabled, pedited->dehaze.enabled); + assignFromKeyfile(keyFile, "Dehaze", "Strength", pedited, dehaze.strength, pedited->dehaze.strength); + } + if (keyFile.has_group("Film Simulation")) { assignFromKeyfile(keyFile, "Film Simulation", "Enabled", pedited, filmSimulation.enabled, pedited->filmSimulation.enabled); assignFromKeyfile(keyFile, "Film Simulation", "ClutFilename", pedited, filmSimulation.clutFilename, pedited->filmSimulation.clutFilename); diff --git a/rtengine/procparams.h b/rtengine/procparams.h index 700c6271c..19fe0a376 100644 --- a/rtengine/procparams.h +++ b/rtengine/procparams.h @@ -1227,6 +1227,17 @@ struct SoftLightParams { }; +struct DehazeParams { + bool enabled; + int strength; + + DehazeParams(); + + bool operator==(const DehazeParams &other) const; + bool operator!=(const DehazeParams &other) const; +}; + + /** * Parameters for RAW demosaicing, common to all sensor type */ @@ -1438,6 +1449,7 @@ public: HSVEqualizerParams hsvequalizer; ///< hsv wavelet parameters FilmSimulationParams filmSimulation; ///< film simulation parameters SoftLightParams softlight; ///< softlight parameters + DehazeParams dehaze; ///< dehaze parameters int rank; ///< Custom image quality ranking int colorlabel; ///< Custom color label bool inTrash; ///< Marks deleted image diff --git a/rtengine/rtthumbnail.cc b/rtengine/rtthumbnail.cc index 79dee36bf..bb710ee83 100644 --- a/rtengine/rtthumbnail.cc +++ b/rtengine/rtthumbnail.cc @@ -1200,6 +1200,7 @@ IImage8* Thumbnail::processImage (const procparams::ProcParams& params, eSensorT ipf.firstAnalysis (baseImg, params, hist16); + ipf.dehaze(baseImg); if (params.fattal.enabled) { ipf.ToneMapFattal02(baseImg); } diff --git a/rtengine/simpleprocess.cc b/rtengine/simpleprocess.cc index fbee20f44..0846eacbd 100644 --- a/rtengine/simpleprocess.cc +++ b/rtengine/simpleprocess.cc @@ -854,6 +854,7 @@ private: ipf.firstAnalysis (baseImg, params, hist16); + ipf.dehaze(baseImg); if (params.fattal.enabled) { ipf.ToneMapFattal02(baseImg); } diff --git a/rtengine/tmo_fattal02.cc b/rtengine/tmo_fattal02.cc index dc7826501..351d60bc9 100644 --- a/rtengine/tmo_fattal02.cc +++ b/rtengine/tmo_fattal02.cc @@ -952,7 +952,7 @@ inline void rescale_nearest (const Array2Df &src, Array2Df &dst, bool multithrea inline float luminance (float r, float g, float b, TMatrix ws) { - return r * ws[1][0] + g * ws[1][1] + b * ws[1][2]; + return Color::rgbLuminance(r, g, b, ws); } diff --git a/rtgui/CMakeLists.txt b/rtgui/CMakeLists.txt index 8150fbce3..434e8187e 100644 --- a/rtgui/CMakeLists.txt +++ b/rtgui/CMakeLists.txt @@ -156,6 +156,7 @@ set(NONCLISOURCEFILES metadatapanel.cc labgrid.cc softlight.cc + dehaze.cc ) include_directories(BEFORE "${CMAKE_CURRENT_BINARY_DIR}") diff --git a/rtgui/addsetids.h b/rtgui/addsetids.h index 8cf39aa29..1d9c621eb 100644 --- a/rtgui/addsetids.h +++ b/rtgui/addsetids.h @@ -142,6 +142,7 @@ enum { ADDSET_BAYER_DUALDEMOZCONTRAST, ADDSET_XTRANS_FALSE_COLOR_SUPPRESSION, ADDSET_SOFTLIGHT_STRENGTH, + ADDSET_DEHAZE_STRENGTH, ADDSET_PARAM_NUM // THIS IS USED AS A DELIMITER!! }; diff --git a/rtgui/batchtoolpanelcoord.cc b/rtgui/batchtoolpanelcoord.cc index b31f41e4f..13b1f6677 100644 --- a/rtgui/batchtoolpanelcoord.cc +++ b/rtgui/batchtoolpanelcoord.cc @@ -202,6 +202,7 @@ void BatchToolPanelCoordinator::initSession () colortoning->setAdjusterBehavior (options.baBehav[ADDSET_COLORTONING_SPLIT], options.baBehav[ADDSET_COLORTONING_SATTHRESHOLD], options.baBehav[ADDSET_COLORTONING_SATOPACITY], options.baBehav[ADDSET_COLORTONING_STRENGTH], options.baBehav[ADDSET_COLORTONING_BALANCE]); filmSimulation->setAdjusterBehavior(options.baBehav[ADDSET_FILMSIMULATION_STRENGTH]); softlight->setAdjusterBehavior(options.baBehav[ADDSET_SOFTLIGHT_STRENGTH]); + dehaze->setAdjusterBehavior(options.baBehav[ADDSET_DEHAZE_STRENGTH]); retinex->setAdjusterBehavior (options.baBehav[ADDSET_RETI_STR], options.baBehav[ADDSET_RETI_NEIGH], options.baBehav[ADDSET_RETI_LIMD], options.baBehav[ADDSET_RETI_OFFS], options.baBehav[ADDSET_RETI_VART], options.baBehav[ADDSET_RETI_GAM], options.baBehav[ADDSET_RETI_SLO]); chmixer->setAdjusterBehavior (options.baBehav[ADDSET_CHMIXER] ); @@ -292,6 +293,7 @@ void BatchToolPanelCoordinator::initSession () if (options.baBehav[ADDSET_COLORTONING_STRENGTH]) { pparams.colorToning.strength = 0; } if (options.baBehav[ADDSET_FILMSIMULATION_STRENGTH]) { pparams.filmSimulation.strength = 0; } if (options.baBehav[ADDSET_SOFTLIGHT_STRENGTH]) { pparams.softlight.strength = 0; } + if (options.baBehav[ADDSET_DEHAZE_STRENGTH]) { pparams.dehaze.strength = 0; } if (options.baBehav[ADDSET_ROTATE_DEGREE]) { pparams.rotate.degree = 0; } if (options.baBehav[ADDSET_RESIZE_SCALE]) { pparams.resize.scale = 0; } if (options.baBehav[ADDSET_DIST_AMOUNT]) { pparams.distortion.amount = 0; } diff --git a/rtgui/dehaze.cc b/rtgui/dehaze.cc new file mode 100644 index 000000000..6f4814e55 --- /dev/null +++ b/rtgui/dehaze.cc @@ -0,0 +1,115 @@ +/** -*- C++ -*- + * + * This file is part of RawTherapee. + * + * Copyright (c) 2018 Alberto Griggio + * + * RawTherapee is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * RawTherapee is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with RawTherapee. If not, see . + */ +#include "dehaze.h" +#include "eventmapper.h" +#include +#include + +using namespace rtengine; +using namespace rtengine::procparams; + +Dehaze::Dehaze(): FoldableToolPanel(this, "dehaze", M("TP_DEHAZE_LABEL"), false, true) +{ + auto m = ProcEventMapper::getInstance(); + EvDehazeEnabled = m->newEvent(HDR, "HISTORY_MSG_DEHAZE_ENABLED"); + EvDehazeStrength = m->newEvent(HDR, "HISTORY_MSG_DEHAZE_STRENGTH"); + + strength = Gtk::manage(new Adjuster(M("TP_DEHAZE_STRENGTH"), 0., 100., 1., 50.)); + strength->setAdjusterListener(this); + strength->show(); + + pack_start(*strength); +} + + +void Dehaze::read(const ProcParams *pp, const ParamsEdited *pedited) +{ + disableListener(); + + if (pedited) { + strength->setEditedState(pedited->dehaze.strength ? Edited : UnEdited); + set_inconsistent(multiImage && !pedited->dehaze.enabled); + } + + setEnabled(pp->dehaze.enabled); + strength->setValue(pp->dehaze.strength); + + enableListener(); +} + + +void Dehaze::write(ProcParams *pp, ParamsEdited *pedited) +{ + pp->dehaze.strength = strength->getValue(); + pp->dehaze.enabled = getEnabled(); + + if (pedited) { + pedited->dehaze.strength = strength->getEditedState(); + pedited->dehaze.enabled = !get_inconsistent(); + } +} + +void Dehaze::setDefaults(const ProcParams *defParams, const ParamsEdited *pedited) +{ + strength->setDefault(defParams->dehaze.strength); + + if (pedited) { + strength->setDefaultEditedState(pedited->dehaze.strength ? Edited : UnEdited); + } else { + strength->setDefaultEditedState(Irrelevant); + } +} + + +void Dehaze::adjusterChanged(Adjuster* a, double newval) +{ + if (listener && getEnabled()) { + listener->panelChanged(EvDehazeStrength, a->getTextValue()); + } +} + + +void Dehaze::enabledChanged () +{ + if (listener) { + if (get_inconsistent()) { + listener->panelChanged(EvDehazeEnabled, M("GENERAL_UNCHANGED")); + } else if (getEnabled()) { + listener->panelChanged(EvDehazeEnabled, M("GENERAL_ENABLED")); + } else { + listener->panelChanged(EvDehazeEnabled, M("GENERAL_DISABLED")); + } + } +} + + +void Dehaze::setBatchMode(bool batchMode) +{ + ToolPanel::setBatchMode(batchMode); + + strength->showEditedCB(); +} + + +void Dehaze::setAdjusterBehavior(bool strengthAdd) +{ + strength->setAddMode(strengthAdd); +} + diff --git a/rtgui/dehaze.h b/rtgui/dehaze.h new file mode 100644 index 000000000..3617f13ea --- /dev/null +++ b/rtgui/dehaze.h @@ -0,0 +1,47 @@ +/** -*- C++ -*- + * + * This file is part of RawTherapee. + * + * Copyright (c) 2018 Alberto Griggio + * + * RawTherapee is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * RawTherapee is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with RawTherapee. If not, see . + */ +#pragma once + +#include +#include "adjuster.h" +#include "toolpanel.h" + +class Dehaze: public ToolParamBlock, public AdjusterListener, public FoldableToolPanel +{ +private: + Adjuster *strength; + + rtengine::ProcEvent EvDehazeEnabled; + rtengine::ProcEvent EvDehazeStrength; + +public: + + Dehaze(); + + void read(const rtengine::procparams::ProcParams *pp, const ParamsEdited *pedited=nullptr); + void write(rtengine::procparams::ProcParams *pp, ParamsEdited *pedited=nullptr); + void setDefaults(const rtengine::procparams::ProcParams *defParams, const ParamsEdited *pedited=nullptr); + void setBatchMode(bool batchMode); + + void adjusterChanged(Adjuster *a, double newval); + void enabledChanged(); + void setAdjusterBehavior(bool strengthAdd); +}; + diff --git a/rtgui/paramsedited.cc b/rtgui/paramsedited.cc index 342d9adf9..fef8da8e6 100644 --- a/rtgui/paramsedited.cc +++ b/rtgui/paramsedited.cc @@ -566,6 +566,8 @@ void ParamsEdited::set(bool v) filmSimulation.strength = v; softlight.enabled = v; softlight.strength = v; + dehaze.enabled = v; + dehaze.strength = v; metadata.mode = v; exif = v; @@ -1119,6 +1121,8 @@ void ParamsEdited::initFrom(const std::vector& filmSimulation.strength = filmSimulation.strength && p.filmSimulation.strength == other.filmSimulation.strength; softlight.enabled = softlight.enabled && p.softlight.enabled == other.softlight.enabled; softlight.strength = softlight.strength && p.softlight.strength == other.softlight.strength; + dehaze.enabled = dehaze.enabled && p.dehaze.enabled == other.dehaze.enabled; + dehaze.strength = dehaze.strength && p.dehaze.strength == other.dehaze.strength; metadata.mode = metadata.mode && p.metadata.mode == other.metadata.mode; // How the hell can we handle that??? @@ -3112,6 +3116,14 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng if (softlight.strength) { toEdit.softlight.strength = dontforceSet && options.baBehav[ADDSET_SOFTLIGHT_STRENGTH] ? toEdit.softlight.strength + mods.softlight.strength : mods.softlight.strength; } + + if (dehaze.enabled) { + toEdit.dehaze.enabled = mods.dehaze.enabled; + } + + if (dehaze.strength) { + toEdit.dehaze.strength = dontforceSet && options.baBehav[ADDSET_DEHAZE_STRENGTH] ? toEdit.dehaze.strength + mods.dehaze.strength : mods.dehaze.strength; + } if (metadata.mode) { toEdit.metadata.mode = mods.metadata.mode; diff --git a/rtgui/paramsedited.h b/rtgui/paramsedited.h index 177b05d85..6a2076032 100644 --- a/rtgui/paramsedited.h +++ b/rtgui/paramsedited.h @@ -724,6 +724,14 @@ public: bool strength; }; +class DehazeParamsEdited +{ +public: + bool enabled; + bool strength; +}; + + class RAWParamsEdited { @@ -865,6 +873,7 @@ public: HSVEqualizerParamsEdited hsvequalizer; FilmSimulationParamsEdited filmSimulation; SoftLightParamsEdited softlight; + DehazeParamsEdited dehaze; MetaDataParamsEdited metadata; bool exif; bool iptc; diff --git a/rtgui/partialpastedlg.cc b/rtgui/partialpastedlg.cc index 6b192dba9..065deef6a 100644 --- a/rtgui/partialpastedlg.cc +++ b/rtgui/partialpastedlg.cc @@ -65,6 +65,7 @@ PartialPasteDlg::PartialPasteDlg (const Glib::ustring &title, Gtk::Window* paren dirpyrden = Gtk::manage (new Gtk::CheckButton (M("PARTIALPASTE_DIRPYRDENOISE"))); defringe = Gtk::manage (new Gtk::CheckButton (M("PARTIALPASTE_DEFRINGE"))); dirpyreq = Gtk::manage (new Gtk::CheckButton (M("PARTIALPASTE_DIRPYREQUALIZER"))); + dehaze = Gtk::manage (new Gtk::CheckButton (M("PARTIALPASTE_DEHAZE")) ); // Advanced Settings: retinex = Gtk::manage (new Gtk::CheckButton (M("PARTIALPASTE_RETINEX"))); @@ -168,6 +169,7 @@ PartialPasteDlg::PartialPasteDlg (const Glib::ustring &title, Gtk::Window* paren vboxes[1]->pack_start (*dirpyrden, Gtk::PACK_SHRINK, 2); vboxes[1]->pack_start (*defringe, Gtk::PACK_SHRINK, 2); vboxes[1]->pack_start (*dirpyreq, Gtk::PACK_SHRINK, 2); + vboxes[1]->pack_start (*dehaze, Gtk::PACK_SHRINK, 2); //COLOR vboxes[2]->pack_start (*color, Gtk::PACK_SHRINK, 2); @@ -327,6 +329,7 @@ PartialPasteDlg::PartialPasteDlg (const Glib::ustring &title, Gtk::Window* paren dirpyrdenConn = dirpyrden->signal_toggled().connect (sigc::bind (sigc::mem_fun(*detail, &Gtk::CheckButton::set_inconsistent), true)); defringeConn = defringe->signal_toggled().connect (sigc::bind (sigc::mem_fun(*detail, &Gtk::CheckButton::set_inconsistent), true)); dirpyreqConn = dirpyreq->signal_toggled().connect (sigc::bind (sigc::mem_fun(*detail, &Gtk::CheckButton::set_inconsistent), true)); + dehazeConn = dehaze->signal_toggled().connect (sigc::bind (sigc::mem_fun(*detail, &Gtk::CheckButton::set_inconsistent), true)); // Advanced Settings: retinexConn = retinex->signal_toggled().connect (sigc::bind (sigc::mem_fun(*advanced, &Gtk::CheckButton::set_inconsistent), true)); @@ -534,6 +537,7 @@ void PartialPasteDlg::detailToggled () ConnectionBlocker dirpyrdenBlocker(dirpyrdenConn); ConnectionBlocker defringeBlocker(defringeConn); ConnectionBlocker dirpyreqBlocker(dirpyreqConn); + ConnectionBlocker dehazeBlocker(dehazeConn); detail->set_inconsistent (false); @@ -545,6 +549,7 @@ void PartialPasteDlg::detailToggled () dirpyrden->set_active (detail->get_active ()); defringe->set_active (detail->get_active ()); dirpyreq->set_active (detail->get_active ()); + dehaze->set_active (detail->get_active ()); } void PartialPasteDlg::advancedToggled () @@ -762,6 +767,10 @@ void PartialPasteDlg::applyPaste (rtengine::procparams::ProcParams* dstPP, Param filterPE.softlight = falsePE.softlight; } + if (!dehaze->get_active ()) { + filterPE.dehaze = falsePE.dehaze; + } + if (!rgbcurves->get_active ()) { filterPE.rgbCurves = falsePE.rgbCurves; } diff --git a/rtgui/partialpastedlg.h b/rtgui/partialpastedlg.h index 5195d0756..f551ac134 100644 --- a/rtgui/partialpastedlg.h +++ b/rtgui/partialpastedlg.h @@ -63,6 +63,7 @@ public: Gtk::CheckButton* dirpyrden; Gtk::CheckButton* defringe; Gtk::CheckButton* dirpyreq; + Gtk::CheckButton* dehaze; // options in wavelet Gtk::CheckButton* wavelet; @@ -131,7 +132,7 @@ public: sigc::connection everythingConn, basicConn, detailConn, colorConn, lensConn, compositionConn, metaConn, rawConn, advancedConn; sigc::connection wbConn, exposureConn, localcontrastConn, shConn, pcvignetteConn, gradientConn, labcurveConn, colorappearanceConn; - sigc::connection sharpenConn, gradsharpenConn, microcontrastConn, impdenConn, dirpyrdenConn, defringeConn, epdConn, fattalConn, dirpyreqConn, waveletConn, retinexConn; + sigc::connection sharpenConn, gradsharpenConn, microcontrastConn, impdenConn, dirpyrdenConn, defringeConn, epdConn, fattalConn, dirpyreqConn, waveletConn, retinexConn, dehazeConn; sigc::connection vibranceConn, chmixerConn, hsveqConn, rgbcurvesConn, chmixerbwConn, colortoningConn, filmSimulationConn, softlightConn; sigc::connection distortionConn, cacorrConn, vignettingConn, lcpConn; sigc::connection coarserotConn, finerotConn, cropConn, resizeConn, prsharpeningConn, perspectiveConn, commonTransConn; diff --git a/rtgui/preferences.cc b/rtgui/preferences.cc index a7b45c902..33d8489f7 100644 --- a/rtgui/preferences.cc +++ b/rtgui/preferences.cc @@ -255,6 +255,10 @@ Gtk::Widget* Preferences::getBatchProcPanel () appendBehavList (mi, M ("TP_DIRPYRDENOISE_MAIN_GAMMA"), ADDSET_DIRPYRDN_GAMMA, true); appendBehavList (mi, M ("TP_DIRPYRDENOISE_MEDIAN_PASSES"), ADDSET_DIRPYRDN_PASSES, true); + mi = behModel->append (); + mi->set_value ( behavColumns.label, M ("TP_DEHAZE_LABEL") ); + appendBehavList ( mi, M ( "TP_DEHAZE_STRENGTH" ), ADDSET_DEHAZE_STRENGTH, true ); + mi = behModel->append (); mi->set_value (behavColumns.label, M ("TP_WBALANCE_LABEL")); appendBehavList (mi, M ("TP_WBALANCE_TEMPERATURE"), ADDSET_WB_TEMPERATURE, true); diff --git a/rtgui/toolpanelcoord.cc b/rtgui/toolpanelcoord.cc index deecb7682..99367999c 100644 --- a/rtgui/toolpanelcoord.cc +++ b/rtgui/toolpanelcoord.cc @@ -77,6 +77,7 @@ ToolPanelCoordinator::ToolPanelCoordinator (bool batch) : ipc (nullptr), hasChan hsvequalizer = Gtk::manage (new HSVEqualizer ()); filmSimulation = Gtk::manage (new FilmSimulation ()); softlight = Gtk::manage(new SoftLight()); + dehaze = Gtk::manage(new Dehaze()); sensorbayer = Gtk::manage (new SensorBayer ()); sensorxtrans = Gtk::manage (new SensorXTrans ()); bayerprocess = Gtk::manage (new BayerProcess ()); @@ -126,6 +127,7 @@ ToolPanelCoordinator::ToolPanelCoordinator (bool batch) : ipc (nullptr), hasChan addPanel (detailsPanel, dirpyrdenoise); addPanel (detailsPanel, defringe); addPanel (detailsPanel, dirpyrequalizer); + addPanel (detailsPanel, dehaze); addPanel (advancedPanel, wavelet); addPanel (transformPanel, crop); addPanel (transformPanel, resize); diff --git a/rtgui/toolpanelcoord.h b/rtgui/toolpanelcoord.h index 1c46ee54e..ca5c5fac4 100644 --- a/rtgui/toolpanelcoord.h +++ b/rtgui/toolpanelcoord.h @@ -80,6 +80,7 @@ #include "fattaltonemap.h" #include "localcontrast.h" #include "softlight.h" +#include "dehaze.h" #include "guiutils.h" class ImageEditorCoordinator; @@ -136,6 +137,7 @@ protected: DirPyrEqualizer* dirpyrequalizer; HSVEqualizer* hsvequalizer; SoftLight *softlight; + Dehaze *dehaze; FilmSimulation *filmSimulation; SensorBayer * sensorbayer; SensorXTrans * sensorxtrans; From 75964dfd8b767ded7b92ea47f6f57159518e1be4 Mon Sep 17 00:00:00 2001 From: Alberto Griggio Date: Wed, 10 Oct 2018 17:08:36 +0200 Subject: [PATCH 03/42] make sure that dehaze doesn't trigger Fattal tone mapping (bad interaction due to sloppy rebasing) --- rtengine/rtthumbnail.cc | 4 +--- rtengine/simpleprocess.cc | 4 +--- rtengine/tmo_fattal02.cc | 4 ++++ 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/rtengine/rtthumbnail.cc b/rtengine/rtthumbnail.cc index bb710ee83..8a8ce1d9b 100644 --- a/rtengine/rtthumbnail.cc +++ b/rtengine/rtthumbnail.cc @@ -1201,9 +1201,7 @@ IImage8* Thumbnail::processImage (const procparams::ProcParams& params, eSensorT ipf.firstAnalysis (baseImg, params, hist16); ipf.dehaze(baseImg); - if (params.fattal.enabled) { - ipf.ToneMapFattal02(baseImg); - } + ipf.ToneMapFattal02(baseImg); // perform transform if (ipf.needsTransform()) { diff --git a/rtengine/simpleprocess.cc b/rtengine/simpleprocess.cc index 0846eacbd..5cd630315 100644 --- a/rtengine/simpleprocess.cc +++ b/rtengine/simpleprocess.cc @@ -855,9 +855,7 @@ private: ipf.firstAnalysis (baseImg, params, hist16); ipf.dehaze(baseImg); - if (params.fattal.enabled) { - ipf.ToneMapFattal02(baseImg); - } + ipf.ToneMapFattal02(baseImg); // perform transform (excepted resizing) if (ipf.needsTransform()) { diff --git a/rtengine/tmo_fattal02.cc b/rtengine/tmo_fattal02.cc index 351d60bc9..124cdbfb1 100644 --- a/rtengine/tmo_fattal02.cc +++ b/rtengine/tmo_fattal02.cc @@ -1014,6 +1014,10 @@ inline int find_fast_dim (int dim) void ImProcFunctions::ToneMapFattal02 (Imagefloat *rgb) { + if (!params->fattal.enabled) { + return; + } + BENCHFUN const int detail_level = 3; From 34321c70125ae89b8874b592e59faba4b9587709 Mon Sep 17 00:00:00 2001 From: Alberto Griggio Date: Wed, 10 Oct 2018 22:49:12 +0200 Subject: [PATCH 04/42] guided filter: properly validate radius parameter before calling boxblur --- rtengine/boxblur.h | 2 -- rtengine/guidedfilter.cc | 1 + 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/rtengine/boxblur.h b/rtengine/boxblur.h index f38c8f6e4..805575b77 100644 --- a/rtengine/boxblur.h +++ b/rtengine/boxblur.h @@ -35,8 +35,6 @@ namespace rtengine template void boxblur (T** src, A** dst, int radx, int rady, int W, int H) { //box blur image; box range = (radx,rady) - radx = min(radx, W-1); - rady = min(rady, H-1); AlignedBuffer* buffer = new AlignedBuffer (W * H); float* temp = buffer->data; diff --git a/rtengine/guidedfilter.cc b/rtengine/guidedfilter.cc index 4f4c5a247..3000e1d5d 100644 --- a/rtengine/guidedfilter.cc +++ b/rtengine/guidedfilter.cc @@ -110,6 +110,7 @@ void guidedFilter(const array2D &guide, const array2D &src, array2 const auto f_mean = [](array2D &d, array2D &s, int rad) -> void { + rad = min(rad, s.width() / 2, s.height() / 2); boxblur(s, d, rad, rad, s.width(), s.height()); }; From 83f5205006dc1ba8f893691780aede843795a85f Mon Sep 17 00:00:00 2001 From: Alberto Griggio Date: Thu, 11 Oct 2018 13:41:41 +0200 Subject: [PATCH 05/42] guided filter: proper bounding of the radius before calling boxblur --- rtengine/boxblur.h | 2 ++ rtengine/guidedfilter.cc | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/rtengine/boxblur.h b/rtengine/boxblur.h index 805575b77..71452ceae 100644 --- a/rtengine/boxblur.h +++ b/rtengine/boxblur.h @@ -35,6 +35,8 @@ namespace rtengine template void boxblur (T** src, A** dst, int radx, int rady, int W, int H) { //box blur image; box range = (radx,rady) + assert(2*radx+1 < W); + assert(2*rady+1 < H); AlignedBuffer* buffer = new AlignedBuffer (W * H); float* temp = buffer->data; diff --git a/rtengine/guidedfilter.cc b/rtengine/guidedfilter.cc index 3000e1d5d..f6b702a73 100644 --- a/rtengine/guidedfilter.cc +++ b/rtengine/guidedfilter.cc @@ -110,7 +110,7 @@ void guidedFilter(const array2D &guide, const array2D &src, array2 const auto f_mean = [](array2D &d, array2D &s, int rad) -> void { - rad = min(rad, s.width() / 2, s.height() / 2); + rad = LIM(rad, 0, (min(s.width(), s.height()) - 1) / 2 - 1); boxblur(s, d, rad, rad, s.width(), s.height()); }; From 74ae459bf2c8782ced1ab592e4a2e5416ecf1f04 Mon Sep 17 00:00:00 2001 From: Alberto Griggio Date: Thu, 11 Oct 2018 13:43:45 +0200 Subject: [PATCH 06/42] dehaze: added more user-controllable parameters --- rtdata/languages/default | 6 +++ rtengine/ipdehaze.cc | 95 ++++++++++++++++++++++++++++++++++++---- rtengine/procparams.cc | 16 ++++++- rtengine/procparams.h | 3 ++ rtgui/dehaze.cc | 54 ++++++++++++++++++++++- rtgui/dehaze.h | 7 +++ rtgui/paramsedited.cc | 18 ++++++++ rtgui/paramsedited.h | 3 ++ 8 files changed, 190 insertions(+), 12 deletions(-) diff --git a/rtdata/languages/default b/rtdata/languages/default index dcf626948..facf89498 100644 --- a/rtdata/languages/default +++ b/rtdata/languages/default @@ -728,7 +728,10 @@ HISTORY_MSG_492;RGB Curves HISTORY_MSG_493;L*a*b* Adjustments HISTORY_MSG_CLAMPOOG;Clip out-of-gamut colors HISTORY_MSG_COLORTONING_LABGRID_VALUE;CT - Color correction +HISTORY_MSG_DEHAZE_DEPTH;Dehaze - Depth +HISTORY_MSG_DEHAZE_DETAIL;Dehaze - Detail HISTORY_MSG_DEHAZE_ENABLED;Haze Removal +HISTORY_MSG_DEHAZE_SHOW_DEPTH_MAP;Dehaze - Show depth map HISTORY_MSG_DEHAZE_STRENGTH;Dehaze - Strength HISTORY_MSG_DUALDEMOSAIC_CONTRAST;AMaZE+VNG4 - Contrast threshold HISTORY_MSG_HISTMATCHING;Auto-matched tone curve @@ -1508,7 +1511,10 @@ TP_DARKFRAME_LABEL;Dark-Frame TP_DEFRINGE_LABEL;Defringe TP_DEFRINGE_RADIUS;Radius TP_DEFRINGE_THRESHOLD;Threshold +TP_DEHAZE_DEPTH;Depth +TP_DEHAZE_DETAIL;Detail TP_DEHAZE_LABEL;Haze Removal +TP_DEHAZE_SHOW_DEPTH_MAP;Show Depth Map TP_DEHAZE_STRENGTH;Strength TP_DIRPYRDENOISE_CHROMINANCE_AMZ;Auto multi-zones TP_DIRPYRDENOISE_CHROMINANCE_AUTOGLOBAL;Automatic global diff --git a/rtengine/ipdehaze.cc b/rtengine/ipdehaze.cc index aed647417..7fa1988ce 100644 --- a/rtengine/ipdehaze.cc +++ b/rtengine/ipdehaze.cc @@ -218,6 +218,59 @@ void get_luminance(Imagefloat *img, array2D &Y, TMatrix ws, bool multithr } +void apply_contrast(array2D &dark, int contrast, double scale, bool multithread) +{ + if (contrast) { + const int W = dark.width(); + const int H = dark.height(); + + double tot = 0.0; +#ifdef _OPENMP + #pragma omp parallel for if (multithread) +#endif + for (int y = 0; y < H; ++y) { + double ytot = 0.0; + for (int x = 0; x < W; ++x) { + ytot += dark[y][x]; + } +#ifdef _OPENMP + #pragma omp critical +#endif + { + tot += ytot; + } + } + + float avg = tot / (W * H); + + std::vector pts = { + DCT_NURBS, + 0, //black point. Value in [0 ; 1] range + 0, //black point. Value in [0 ; 1] range + + avg - avg * (0.6 - contrast / 250.0), //toe point + avg - avg * (0.6 + contrast / 250.0), //value at toe point + + avg + (1 - avg) * (0.6 - contrast / 250.0), //shoulder point + avg + (1 - avg) * (0.6 + contrast / 250.0), //value at shoulder point + + 1., // white point + 1. // value at white point + }; + + const DiagonalCurve curve(pts, CURVES_MIN_POLY_POINTS / scale); + +#ifdef _OPENMP + #pragma omp parallel for if (multithread) +#endif + for (int y = 0; y < H; ++y) { + for (int x = 0; x < W; ++x) { + dark[y][x] = curve.getVal(dark[y][x]); + } + } + } +} + } // namespace @@ -231,14 +284,14 @@ void ImProcFunctions::dehaze(Imagefloat *img) const int W = img->getWidth(); const int H = img->getHeight(); - const float strength = LIM01(float(params->dehaze.strength) / 100.f * 0.9f); + float strength = LIM01(float(params->dehaze.strength) / 100.f * 0.9f); if (options.rtSettings.verbose) { std::cout << "dehaze: strength = " << strength << std::endl; } array2D dark(W, H); - const int patchsize = std::max(W / 200, 2); + const int patchsize = std::max(W / (200 + max(params->dehaze.detail, 0)), 2); int npatches = get_dark_channel(*img, dark, patchsize, nullptr, multiThread); DEBUG_DUMP(dark); @@ -268,18 +321,27 @@ void ImProcFunctions::dehaze(Imagefloat *img) array2D &t_tilde = dark; get_dark_channel(*img, dark, patchsize, ambient, multiThread); + apply_contrast(dark, params->dehaze.depth, scale, multiThread); DEBUG_DUMP(t_tilde); - + + if (!params->dehaze.showDepthMap) { #ifdef _OPENMP - #pragma omp parallel for if (multiThread) + #pragma omp parallel for if (multiThread) #endif - for (int y = 0; y < H; ++y) { - for (int x = 0; x < W; ++x) { - dark[y][x] = 1.f - strength * dark[y][x]; + for (int y = 0; y < H; ++y) { + for (int x = 0; x < W; ++x) { + dark[y][x] = 1.f - strength * dark[y][x]; + } } } - const int radius = patchsize * 2; + float mult = 2.f; + if (params->dehaze.detail > 0) { + mult -= (params->dehaze.detail / 100.f) * 1.9f; + } else { + mult -= params->dehaze.detail / 10.f; + } + const int radius = max(int(patchsize * mult), 1); const float epsilon = 2.5e-4; array2D &t = t_tilde; @@ -287,6 +349,19 @@ void ImProcFunctions::dehaze(Imagefloat *img) DEBUG_DUMP(t); + + if (params->dehaze.showDepthMap) { +#ifdef _OPENMP + #pragma omp parallel for if (multiThread) +#endif + for (int y = 0; y < H; ++y) { + for (int x = 0; x < W; ++x) { + img->r(y, x) = img->g(y, x) = img->b(y, x) = t[y][x] * 65535.f; + } + } + return; + } + const float t0 = 0.01; #ifdef _OPENMP #pragma omp parallel for if (multiThread) @@ -313,7 +388,7 @@ void ImProcFunctions::dehaze(Imagefloat *img) if (newmed > 1e-5f) { const float f1 = oldmed / newmed; - const float f = f1 * 65535.f; + const float f = /* f1 * */ 65535.f; #ifdef _OPENMP #pragma omp parallel for if (multiThread) #endif @@ -328,6 +403,8 @@ void ImProcFunctions::dehaze(Imagefloat *img) Color::hsl2rgbfloat(h, s, l, img->r(y, x), img->g(y, x), img->b(y, x)); } } + } else { + img->normalizeFloatTo65535(); } } diff --git a/rtengine/procparams.cc b/rtengine/procparams.cc index ceace7c3b..17afb3371 100644 --- a/rtengine/procparams.cc +++ b/rtengine/procparams.cc @@ -2376,7 +2376,10 @@ bool SoftLightParams::operator !=(const SoftLightParams& other) const DehazeParams::DehazeParams() : enabled(false), - strength(50) + strength(50), + showDepthMap(false), + depth(0), + detail(0) { } @@ -2384,7 +2387,10 @@ bool DehazeParams::operator ==(const DehazeParams& other) const { return enabled == other.enabled - && strength == other.strength; + && strength == other.strength + && showDepthMap == other.showDepthMap + && depth == other.depth + && detail == other.detail; } bool DehazeParams::operator !=(const DehazeParams& other) const @@ -3062,6 +3068,9 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo // Dehaze saveToKeyfile(!pedited || pedited->dehaze.enabled, "Dehaze", "Enabled", dehaze.enabled, keyFile); saveToKeyfile(!pedited || pedited->dehaze.strength, "Dehaze", "Strength", dehaze.strength, keyFile); + saveToKeyfile(!pedited || pedited->dehaze.showDepthMap, "Dehaze", "ShowDepthMap", dehaze.showDepthMap, keyFile); + saveToKeyfile(!pedited || pedited->dehaze.depth, "Dehaze", "Depth", dehaze.depth, keyFile); + saveToKeyfile(!pedited || pedited->dehaze.detail, "Dehaze", "Detail", dehaze.detail, keyFile); // Directional pyramid denoising saveToKeyfile(!pedited || pedited->dirpyrDenoise.enabled, "Directional Pyramid Denoising", "Enabled", dirpyrDenoise.enabled, keyFile); @@ -4647,6 +4656,9 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited) if (keyFile.has_group("Dehaze")) { assignFromKeyfile(keyFile, "Dehaze", "Enabled", pedited, dehaze.enabled, pedited->dehaze.enabled); assignFromKeyfile(keyFile, "Dehaze", "Strength", pedited, dehaze.strength, pedited->dehaze.strength); + assignFromKeyfile(keyFile, "Dehaze", "ShowDepthMap", pedited, dehaze.showDepthMap, pedited->dehaze.showDepthMap); + assignFromKeyfile(keyFile, "Dehaze", "Depth", pedited, dehaze.depth, pedited->dehaze.depth); + assignFromKeyfile(keyFile, "Dehaze", "Detail", pedited, dehaze.detail, pedited->dehaze.detail); } if (keyFile.has_group("Film Simulation")) { diff --git a/rtengine/procparams.h b/rtengine/procparams.h index 19fe0a376..143fedbe8 100644 --- a/rtengine/procparams.h +++ b/rtengine/procparams.h @@ -1230,6 +1230,9 @@ struct SoftLightParams { struct DehazeParams { bool enabled; int strength; + bool showDepthMap; + int depth; + int detail; DehazeParams(); diff --git a/rtgui/dehaze.cc b/rtgui/dehaze.cc index 6f4814e55..ef5075ab7 100644 --- a/rtgui/dehaze.cc +++ b/rtgui/dehaze.cc @@ -30,12 +30,30 @@ Dehaze::Dehaze(): FoldableToolPanel(this, "dehaze", M("TP_DEHAZE_LABEL"), false, auto m = ProcEventMapper::getInstance(); EvDehazeEnabled = m->newEvent(HDR, "HISTORY_MSG_DEHAZE_ENABLED"); EvDehazeStrength = m->newEvent(HDR, "HISTORY_MSG_DEHAZE_STRENGTH"); + EvDehazeShowDepthMap = m->newEvent(HDR, "HISTORY_MSG_DEHAZE_SHOW_DEPTH_MAP"); + EvDehazeDepth = m->newEvent(HDR, "HISTORY_MSG_DEHAZE_DEPTH"); + EvDehazeDetail = m->newEvent(HDR, "HISTORY_MSG_DEHAZE_DETAIL"); strength = Gtk::manage(new Adjuster(M("TP_DEHAZE_STRENGTH"), 0., 100., 1., 50.)); strength->setAdjusterListener(this); strength->show(); + depth = Gtk::manage(new Adjuster(M("TP_DEHAZE_DEPTH"), -100., 100., 1., 0.)); + depth->setAdjusterListener(this); + depth->show(); + + detail = Gtk::manage(new Adjuster(M("TP_DEHAZE_DETAIL"), -100, 100, 1, 0)); + detail->setAdjusterListener(this); + detail->show(); + + showDepthMap = Gtk::manage(new Gtk::CheckButton(M("TP_DEHAZE_SHOW_DEPTH_MAP"))); + showDepthMap->signal_toggled().connect(sigc::mem_fun(*this, &Dehaze::showDepthMapChanged)); + showDepthMap->show(); + pack_start(*strength); + pack_start(*depth); + pack_start(*detail); + pack_start(*showDepthMap); } @@ -45,11 +63,17 @@ void Dehaze::read(const ProcParams *pp, const ParamsEdited *pedited) if (pedited) { strength->setEditedState(pedited->dehaze.strength ? Edited : UnEdited); + depth->setEditedState(pedited->dehaze.depth ? Edited : UnEdited); + detail->setEditedState(pedited->dehaze.detail ? Edited : UnEdited); set_inconsistent(multiImage && !pedited->dehaze.enabled); + showDepthMap->set_inconsistent(!pedited->dehaze.showDepthMap); } setEnabled(pp->dehaze.enabled); strength->setValue(pp->dehaze.strength); + depth->setValue(pp->dehaze.depth); + detail->setValue(pp->dehaze.detail); + showDepthMap->set_active(pp->dehaze.showDepthMap); enableListener(); } @@ -58,22 +82,34 @@ void Dehaze::read(const ProcParams *pp, const ParamsEdited *pedited) void Dehaze::write(ProcParams *pp, ParamsEdited *pedited) { pp->dehaze.strength = strength->getValue(); + pp->dehaze.depth = depth->getValue(); + pp->dehaze.detail = detail->getValue(); pp->dehaze.enabled = getEnabled(); + pp->dehaze.showDepthMap = showDepthMap->get_active(); if (pedited) { pedited->dehaze.strength = strength->getEditedState(); + pedited->dehaze.depth = depth->getEditedState(); + pedited->dehaze.detail = detail->getEditedState(); pedited->dehaze.enabled = !get_inconsistent(); + pedited->dehaze.showDepthMap = !showDepthMap->get_inconsistent(); } } void Dehaze::setDefaults(const ProcParams *defParams, const ParamsEdited *pedited) { strength->setDefault(defParams->dehaze.strength); + depth->setDefault(defParams->dehaze.depth); + detail->setDefault(defParams->dehaze.detail); if (pedited) { strength->setDefaultEditedState(pedited->dehaze.strength ? Edited : UnEdited); + depth->setDefaultEditedState(pedited->dehaze.depth ? Edited : UnEdited); + detail->setDefaultEditedState(pedited->dehaze.detail ? Edited : UnEdited); } else { strength->setDefaultEditedState(Irrelevant); + depth->setDefaultEditedState(Irrelevant); + detail->setDefaultEditedState(Irrelevant); } } @@ -81,7 +117,13 @@ void Dehaze::setDefaults(const ProcParams *defParams, const ParamsEdited *pedite void Dehaze::adjusterChanged(Adjuster* a, double newval) { if (listener && getEnabled()) { - listener->panelChanged(EvDehazeStrength, a->getTextValue()); + if (a == strength) { + listener->panelChanged(EvDehazeStrength, a->getTextValue()); + } else if (a == depth) { + listener->panelChanged(EvDehazeDepth, a->getTextValue()); + } else if (a == detail) { + listener->panelChanged(EvDehazeDetail, a->getTextValue()); + } } } @@ -100,11 +142,21 @@ void Dehaze::enabledChanged () } +void Dehaze::showDepthMapChanged() +{ + if (listener) { + listener->panelChanged(EvDehazeShowDepthMap, showDepthMap->get_active() ? M("GENERAL_ENABLED") : M("GENERAL_DISABLED")); + } +} + + void Dehaze::setBatchMode(bool batchMode) { ToolPanel::setBatchMode(batchMode); strength->showEditedCB(); + depth->showEditedCB(); + detail->showEditedCB(); } diff --git a/rtgui/dehaze.h b/rtgui/dehaze.h index 3617f13ea..ae6097c86 100644 --- a/rtgui/dehaze.h +++ b/rtgui/dehaze.h @@ -27,9 +27,15 @@ class Dehaze: public ToolParamBlock, public AdjusterListener, public FoldableToo { private: Adjuster *strength; + Adjuster *depth; + Adjuster *detail; + Gtk::CheckButton *showDepthMap; rtengine::ProcEvent EvDehazeEnabled; rtengine::ProcEvent EvDehazeStrength; + rtengine::ProcEvent EvDehazeDepth; + rtengine::ProcEvent EvDehazeDetail; + rtengine::ProcEvent EvDehazeShowDepthMap; public: @@ -42,6 +48,7 @@ public: void adjusterChanged(Adjuster *a, double newval); void enabledChanged(); + void showDepthMapChanged(); void setAdjusterBehavior(bool strengthAdd); }; diff --git a/rtgui/paramsedited.cc b/rtgui/paramsedited.cc index fef8da8e6..ffc1bd19c 100644 --- a/rtgui/paramsedited.cc +++ b/rtgui/paramsedited.cc @@ -568,6 +568,9 @@ void ParamsEdited::set(bool v) softlight.strength = v; dehaze.enabled = v; dehaze.strength = v; + dehaze.showDepthMap = v; + dehaze.depth = v; + dehaze.detail = v; metadata.mode = v; exif = v; @@ -1123,6 +1126,9 @@ void ParamsEdited::initFrom(const std::vector& softlight.strength = softlight.strength && p.softlight.strength == other.softlight.strength; dehaze.enabled = dehaze.enabled && p.dehaze.enabled == other.dehaze.enabled; dehaze.strength = dehaze.strength && p.dehaze.strength == other.dehaze.strength; + dehaze.showDepthMap = dehaze.showDepthMap && p.dehaze.showDepthMap == other.dehaze.showDepthMap; + dehaze.depth = dehaze.depth && p.dehaze.depth == other.dehaze.depth; + dehaze.detail = dehaze.detail && p.dehaze.detail == other.dehaze.detail; metadata.mode = metadata.mode && p.metadata.mode == other.metadata.mode; // How the hell can we handle that??? @@ -3125,6 +3131,18 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng toEdit.dehaze.strength = dontforceSet && options.baBehav[ADDSET_DEHAZE_STRENGTH] ? toEdit.dehaze.strength + mods.dehaze.strength : mods.dehaze.strength; } + if (dehaze.depth) { + toEdit.dehaze.depth = mods.dehaze.depth; + } + + if (dehaze.detail) { + toEdit.dehaze.detail = mods.dehaze.detail; + } + + if (dehaze.showDepthMap) { + toEdit.dehaze.showDepthMap = mods.dehaze.showDepthMap; + } + if (metadata.mode) { toEdit.metadata.mode = mods.metadata.mode; } diff --git a/rtgui/paramsedited.h b/rtgui/paramsedited.h index 6a2076032..73a19db88 100644 --- a/rtgui/paramsedited.h +++ b/rtgui/paramsedited.h @@ -729,6 +729,9 @@ class DehazeParamsEdited public: bool enabled; bool strength; + bool showDepthMap; + bool depth; + bool detail; }; From 7c10f92ace3ba69ccccc314ceb49f6d9a5b16f7d Mon Sep 17 00:00:00 2001 From: Alberto Griggio Date: Fri, 12 Oct 2018 16:01:48 +0200 Subject: [PATCH 07/42] dehaze: improved use of the guided filter for less halos --- rtengine/ipdehaze.cc | 152 ++++++++++++++++++++++++++----------------- 1 file changed, 94 insertions(+), 58 deletions(-) diff --git a/rtengine/ipdehaze.cc b/rtengine/ipdehaze.cc index 7fa1988ce..355d7f843 100644 --- a/rtengine/ipdehaze.cc +++ b/rtengine/ipdehaze.cc @@ -58,28 +58,28 @@ namespace { #endif -int get_dark_channel(const Imagefloat &src, array2D &dst, +int get_dark_channel(const array2D &R, const array2D &G, const array2D &B, array2D &dst, int patchsize, float *ambient, bool multithread) { - const int w = src.getWidth(); - const int h = src.getHeight(); + const int W = R.width(); + const int H = R.height(); int npatches = 0; #ifdef _OPENMP #pragma omp parallel for if (multithread) #endif - for (int y = 0; y < src.getHeight(); y += patchsize) { - int pH = std::min(y+patchsize, h); - for (int x = 0; x < src.getWidth(); x += patchsize, ++npatches) { + for (int y = 0; y < H; y += patchsize) { + int pH = std::min(y+patchsize, H); + for (int x = 0; x < W; x += patchsize, ++npatches) { float val = RT_INFINITY_F; - int pW = std::min(x+patchsize, w); + int pW = std::min(x+patchsize, W); for (int yy = y; yy < pH; ++yy) { float yval = RT_INFINITY_F; for (int xx = x; xx < pW; ++xx) { - float r = src.r(yy, xx); - float g = src.g(yy, xx); - float b = src.b(yy, xx); + float r = R[yy][xx]; + float g = G[yy][xx]; + float b = B[yy][xx]; if (ambient) { r /= ambient[0]; g /= ambient[1]; @@ -89,14 +89,16 @@ int get_dark_channel(const Imagefloat &src, array2D &dst, } val = min(val, yval); } + val = LIM01(val); for (int yy = y; yy < pH; ++yy) { std::fill(dst[yy]+x, dst[yy]+pW, val); } + float val2 = RT_INFINITY_F; for (int yy = y; yy < pH; ++yy) { for (int xx = x; xx < pW; ++xx) { - float r = src.r(yy, xx); - float g = src.g(yy, xx); - float b = src.b(yy, xx); + float r = R[yy][xx]; + float g = G[yy][xx]; + float b = B[yy][xx]; if (ambient) { r /= ambient[0]; g /= ambient[1]; @@ -104,7 +106,18 @@ int get_dark_channel(const Imagefloat &src, array2D &dst, } float l = min(r, g, b); if (l >= 2.f * val) { - dst[yy][xx] = l; + val2 = min(val2, l); + dst[yy][xx] = -1; + } + } + } + if (val2 < RT_INFINITY_F) { + val2 = LIM01(val2); + for (int yy = y; yy < pH; ++yy) { + for (int xx = x; xx < pW; ++xx) { + if (dst[yy][xx] < 0.f) { + dst[yy][xx] = val2; + } } } } @@ -115,10 +128,10 @@ int get_dark_channel(const Imagefloat &src, array2D &dst, } -int estimate_ambient_light(const Imagefloat *img, const array2D &dark, const array2D &Y, int patchsize, int npatches, float ambient[3]) +int estimate_ambient_light(const array2D &R, const array2D &G, const array2D &B, const array2D &dark, const array2D &Y, int patchsize, int npatches, float ambient[3]) { - const int W = img->getWidth(); - const int H = img->getHeight(); + const int W = R.width(); + const int H = R.height(); const auto get_percentile = [](std::priority_queue &q, float prcnt) -> float @@ -183,9 +196,9 @@ int estimate_ambient_light(const Imagefloat *img, const array2D &dark, co for (int y = p.second; y < pH; ++y) { for (int x = p.first; x < pW; ++x) { if (Y[y][x] >= lim) { - float r = img->r(y, x); - float g = img->g(y, x); - float b = img->b(y, x); + float r = R[y][x]; + float g = G[y][x]; + float b = B[y][x]; rr += r; gg += g; bb += b; @@ -218,41 +231,25 @@ void get_luminance(Imagefloat *img, array2D &Y, TMatrix ws, bool multithr } -void apply_contrast(array2D &dark, int contrast, double scale, bool multithread) +void apply_contrast(array2D &dark, float ambient, int contrast, double scale, bool multithread) { if (contrast) { const int W = dark.width(); const int H = dark.height(); - double tot = 0.0; -#ifdef _OPENMP - #pragma omp parallel for if (multithread) -#endif - for (int y = 0; y < H; ++y) { - double ytot = 0.0; - for (int x = 0; x < W; ++x) { - ytot += dark[y][x]; - } -#ifdef _OPENMP - #pragma omp critical -#endif - { - tot += ytot; - } - } - - float avg = tot / (W * H); + float avg = ambient * 0.25f; + float c = contrast * 0.3f; std::vector pts = { DCT_NURBS, 0, //black point. Value in [0 ; 1] range 0, //black point. Value in [0 ; 1] range - avg - avg * (0.6 - contrast / 250.0), //toe point - avg - avg * (0.6 + contrast / 250.0), //value at toe point + avg - avg * (0.6 - c / 250.0), //toe point + avg - avg * (0.6 + c / 250.0), //value at toe point - avg + (1 - avg) * (0.6 - contrast / 250.0), //shoulder point - avg + (1 - avg) * (0.6 + contrast / 250.0), //value at shoulder point + avg + (1 - avg) * (0.6 - c / 250.0), //shoulder point + avg + (1 - avg) * (0.6 + c / 250.0), //value at shoulder point 1., // white point 1. // value at white point @@ -271,6 +268,28 @@ void apply_contrast(array2D &dark, int contrast, double scale, bool multi } } + +void extract_channels(Imagefloat *img, const array2D &Y, array2D &r, array2D &g, array2D &b, int radius, float epsilon, bool multithread) +{ + const int W = img->getWidth(); + const int H = img->getHeight(); + +#ifdef _OPENMP + #pragma omp parallel for if (multithread) +#endif + for (int y = 0; y < H; ++y) { + for (int x = 0; x < W; ++x) { + r[y][x] = img->r(y, x); + g[y][x] = img->g(y, x); + b[y][x] = img->b(y, x); + } + } + + guidedFilter(Y, r, r, radius, epsilon, multithread); + guidedFilter(Y, g, g, radius, epsilon, multithread); + guidedFilter(Y, b, b, radius, epsilon, multithread); +} + } // namespace @@ -289,18 +308,24 @@ void ImProcFunctions::dehaze(Imagefloat *img) if (options.rtSettings.verbose) { std::cout << "dehaze: strength = " << strength << std::endl; } - - array2D dark(W, H); - const int patchsize = std::max(W / (200 + max(params->dehaze.detail, 0)), 2); - int npatches = get_dark_channel(*img, dark, patchsize, nullptr, multiThread); - DEBUG_DUMP(dark); TMatrix ws = ICCStore::getInstance()->workingSpaceMatrix(params->icm.workingProfile); array2D Y(W, H); get_luminance(img, Y, ws, multiThread); + + array2D R(W, H); + array2D G(W, H); + array2D B(W, H); + int patchsize = max(int(20 / scale), 2); + extract_channels(img, Y, R, G, B, patchsize, 1e-1, multiThread); + array2D dark(W, H); + patchsize = std::max(W / (200 + params->dehaze.detail * (SGN(params->dehaze.detail) > 0 ? 4 : 1)), 2); + int npatches = get_dark_channel(R, G, B, dark, patchsize, nullptr, multiThread); + DEBUG_DUMP(dark); + float ambient[3]; - int n = estimate_ambient_light(img, dark, Y, patchsize, npatches, ambient); + int n = estimate_ambient_light(R, G, B, dark, Y, patchsize, npatches, ambient); float ambient_Y = Color::rgbLuminance(ambient[0], ambient[1], ambient[2], ws); if (options.rtSettings.verbose) { @@ -320,8 +345,8 @@ void ImProcFunctions::dehaze(Imagefloat *img) } array2D &t_tilde = dark; - get_dark_channel(*img, dark, patchsize, ambient, multiThread); - apply_contrast(dark, params->dehaze.depth, scale, multiThread); + get_dark_channel(R, G, B, dark, patchsize, ambient, multiThread); + apply_contrast(dark, ambient_Y, params->dehaze.depth, scale, multiThread); DEBUG_DUMP(t_tilde); if (!params->dehaze.showDepthMap) { @@ -344,7 +369,8 @@ void ImProcFunctions::dehaze(Imagefloat *img) const int radius = max(int(patchsize * mult), 1); const float epsilon = 2.5e-4; array2D &t = t_tilde; - + + if (!params->dehaze.showDepthMap) guidedFilter(Y, t_tilde, t, radius, epsilon, multiThread); DEBUG_DUMP(t); @@ -362,16 +388,26 @@ void ImProcFunctions::dehaze(Imagefloat *img) return; } - const float t0 = 0.01; + const float t0 = 0.1; + const float teps = 1e-3; #ifdef _OPENMP #pragma omp parallel for if (multiThread) #endif for (int y = 0; y < H; ++y) { for (int x = 0; x < W; ++x) { - float mt = std::max(t[y][x], t0); - float r = (img->r(y, x) - ambient[0]) / mt + ambient[0]; - float g = (img->g(y, x) - ambient[1]) / mt + ambient[1]; - float b = (img->b(y, x) - ambient[2]) / mt + ambient[2]; + float rgb[3] = { img->r(y, x), img->g(y, x), img->b(y, x) }; + float tl = 1.f - min(rgb[0]/ambient[0], rgb[1]/ambient[1], rgb[2]/ambient[2]); + float tu = t0 - teps; + for (int c = 0; c < 3; ++c) { + if (ambient[c] < 1) { + tu = max(tu, (rgb[c] - ambient[c])/(1.f - ambient[c])); + } + } + float mt = max(t[y][x], t0, tl + teps, tu + teps); + float r = (rgb[0] - ambient[0]) / mt + ambient[0]; + float g = (rgb[1] - ambient[1]) / mt + ambient[1]; + float b = (rgb[2] - ambient[2]) / mt + ambient[2]; + img->r(y, x) = r; img->g(y, x) = g; img->b(y, x) = b; @@ -388,7 +424,7 @@ void ImProcFunctions::dehaze(Imagefloat *img) if (newmed > 1e-5f) { const float f1 = oldmed / newmed; - const float f = /* f1 * */ 65535.f; + const float f = f1 * 65535.f; #ifdef _OPENMP #pragma omp parallel for if (multiThread) #endif From 4d0ddd56e53e312a8d5fd29b61dd34708e91e615 Mon Sep 17 00:00:00 2001 From: Alberto Griggio Date: Tue, 16 Oct 2018 23:20:11 +0200 Subject: [PATCH 08/42] revamped and simplified dehaze -- now it's finally usable --- rtdata/languages/default | 2 - rtengine/ipdehaze.cc | 286 ++++++++++++--------------------------- rtengine/procparams.cc | 8 +- rtengine/procparams.h | 1 - rtgui/dehaze.cc | 18 +-- rtgui/dehaze.h | 2 - rtgui/paramsedited.cc | 6 - rtgui/paramsedited.h | 1 - 8 files changed, 87 insertions(+), 237 deletions(-) diff --git a/rtdata/languages/default b/rtdata/languages/default index facf89498..7dcefdbc8 100644 --- a/rtdata/languages/default +++ b/rtdata/languages/default @@ -729,7 +729,6 @@ HISTORY_MSG_493;L*a*b* Adjustments HISTORY_MSG_CLAMPOOG;Clip out-of-gamut colors HISTORY_MSG_COLORTONING_LABGRID_VALUE;CT - Color correction HISTORY_MSG_DEHAZE_DEPTH;Dehaze - Depth -HISTORY_MSG_DEHAZE_DETAIL;Dehaze - Detail HISTORY_MSG_DEHAZE_ENABLED;Haze Removal HISTORY_MSG_DEHAZE_SHOW_DEPTH_MAP;Dehaze - Show depth map HISTORY_MSG_DEHAZE_STRENGTH;Dehaze - Strength @@ -1512,7 +1511,6 @@ TP_DEFRINGE_LABEL;Defringe TP_DEFRINGE_RADIUS;Radius TP_DEFRINGE_THRESHOLD;Threshold TP_DEHAZE_DEPTH;Depth -TP_DEHAZE_DETAIL;Detail TP_DEHAZE_LABEL;Haze Removal TP_DEHAZE_SHOW_DEPTH_MAP;Show Depth Map TP_DEHAZE_STRENGTH;Strength diff --git a/rtengine/ipdehaze.cc b/rtengine/ipdehaze.cc index 355d7f843..1c5512c2a 100644 --- a/rtengine/ipdehaze.cc +++ b/rtengine/ipdehaze.cc @@ -70,10 +70,10 @@ int get_dark_channel(const array2D &R, const array2D &G, const arr #pragma omp parallel for if (multithread) #endif for (int y = 0; y < H; y += patchsize) { - int pH = std::min(y+patchsize, H); + int pH = min(y+patchsize, H); for (int x = 0; x < W; x += patchsize, ++npatches) { float val = RT_INFINITY_F; - int pW = std::min(x+patchsize, W); + int pW = min(x+patchsize, W); for (int yy = y; yy < pH; ++yy) { float yval = RT_INFINITY_F; for (int xx = x; xx < pW; ++xx) { @@ -93,34 +93,6 @@ int get_dark_channel(const array2D &R, const array2D &G, const arr for (int yy = y; yy < pH; ++yy) { std::fill(dst[yy]+x, dst[yy]+pW, val); } - float val2 = RT_INFINITY_F; - for (int yy = y; yy < pH; ++yy) { - for (int xx = x; xx < pW; ++xx) { - float r = R[yy][xx]; - float g = G[yy][xx]; - float b = B[yy][xx]; - if (ambient) { - r /= ambient[0]; - g /= ambient[1]; - b /= ambient[2]; - } - float l = min(r, g, b); - if (l >= 2.f * val) { - val2 = min(val2, l); - dst[yy][xx] = -1; - } - } - } - if (val2 < RT_INFINITY_F) { - val2 = LIM01(val2); - for (int yy = y; yy < pH; ++yy) { - for (int xx = x; xx < pW; ++xx) { - if (dst[yy][xx] < 0.f) { - dst[yy][xx] = val2; - } - } - } - } } } @@ -128,7 +100,7 @@ int get_dark_channel(const array2D &R, const array2D &G, const arr } -int estimate_ambient_light(const array2D &R, const array2D &G, const array2D &B, const array2D &dark, const array2D &Y, int patchsize, int npatches, float ambient[3]) +float estimate_ambient_light(const array2D &R, const array2D &G, const array2D &B, const array2D &dark, int patchsize, int npatches, float ambient[3]) { const int W = R.width(); const int H = R.height(); @@ -143,7 +115,7 @@ int estimate_ambient_light(const array2D &R, const array2D &G, con return q.top(); }; - float lim = RT_INFINITY_F; + float darklim = RT_INFINITY_F; { std::priority_queue p; for (int y = 0; y < H; y += patchsize) { @@ -151,7 +123,7 @@ int estimate_ambient_light(const array2D &R, const array2D &G, con p.push(dark[y][x]); } } - lim = get_percentile(p, 0.95); + darklim = get_percentile(p, 0.95); } std::vector> patches; @@ -159,7 +131,7 @@ int estimate_ambient_light(const array2D &R, const array2D &G, con for (int y = 0; y < H; y += patchsize) { for (int x = 0; x < W; x += patchsize) { - if (dark[y][x] >= lim) { + if (dark[y][x] >= darklim) { patches.push_back(std::make_pair(x, y)); } } @@ -170,35 +142,36 @@ int estimate_ambient_light(const array2D &R, const array2D &G, con << " patches" << std::endl; } + float bright_lim = RT_INFINITY_F; { std::priority_queue l; for (auto &p : patches) { - const int pW = std::min(p.first+patchsize, W); - const int pH = std::min(p.second+patchsize, H); + const int pW = min(p.first+patchsize, W); + const int pH = min(p.second+patchsize, H); for (int y = p.second; y < pH; ++y) { for (int x = p.first; x < pW; ++x) { - l.push(Y[y][x]); + l.push(R[y][x] + G[y][x] + B[y][x]); } } } - lim = get_percentile(l, 0.95); + bright_lim = get_percentile(l, 0.95); } double rr = 0, gg = 0, bb = 0; int n = 0; for (auto &p : patches) { - const int pW = std::min(p.first+patchsize, W); - const int pH = std::min(p.second+patchsize, H); + const int pW = min(p.first+patchsize, W); + const int pH = min(p.second+patchsize, H); for (int y = p.second; y < pH; ++y) { for (int x = p.first; x < pW; ++x) { - if (Y[y][x] >= lim) { - float r = R[y][x]; - float g = G[y][x]; - float b = B[y][x]; + float r = R[y][x]; + float g = G[y][x]; + float b = B[y][x]; + if (r + g + b >= bright_lim) { rr += r; gg += g; bb += b; @@ -211,65 +184,12 @@ int estimate_ambient_light(const array2D &R, const array2D &G, con ambient[1] = gg / n; ambient[2] = bb / n; - return n; + // taken from darktable + return darklim > 0 ? -1.125f * std::log(darklim) : std::log(std::numeric_limits::max()) / 2; } -void get_luminance(Imagefloat *img, array2D &Y, TMatrix ws, bool multithread) -{ - const int W = img->getWidth(); - const int H = img->getHeight(); - -#ifdef _OPENMP - #pragma omp parallel for if (multithread) -#endif - for (int y = 0; y < H; ++y) { - for (int x = 0; x < W; ++x) { - Y[y][x] = Color::rgbLuminance(img->r(y, x), img->g(y, x), img->b(y, x), ws); - } - } -} - - -void apply_contrast(array2D &dark, float ambient, int contrast, double scale, bool multithread) -{ - if (contrast) { - const int W = dark.width(); - const int H = dark.height(); - - float avg = ambient * 0.25f; - float c = contrast * 0.3f; - - std::vector pts = { - DCT_NURBS, - 0, //black point. Value in [0 ; 1] range - 0, //black point. Value in [0 ; 1] range - - avg - avg * (0.6 - c / 250.0), //toe point - avg - avg * (0.6 + c / 250.0), //value at toe point - - avg + (1 - avg) * (0.6 - c / 250.0), //shoulder point - avg + (1 - avg) * (0.6 + c / 250.0), //value at shoulder point - - 1., // white point - 1. // value at white point - }; - - const DiagonalCurve curve(pts, CURVES_MIN_POLY_POINTS / scale); - -#ifdef _OPENMP - #pragma omp parallel for if (multithread) -#endif - for (int y = 0; y < H; ++y) { - for (int x = 0; x < W; ++x) { - dark[y][x] = curve.getVal(dark[y][x]); - } - } - } -} - - -void extract_channels(Imagefloat *img, const array2D &Y, array2D &r, array2D &g, array2D &b, int radius, float epsilon, bool multithread) +void extract_channels(Imagefloat *img, array2D &r, array2D &g, array2D &b, int radius, float epsilon, bool multithread) { const int W = img->getWidth(); const int H = img->getHeight(); @@ -285,11 +205,12 @@ void extract_channels(Imagefloat *img, const array2D &Y, array2D & } } - guidedFilter(Y, r, r, radius, epsilon, multithread); - guidedFilter(Y, g, g, radius, epsilon, multithread); - guidedFilter(Y, b, b, radius, epsilon, multithread); + guidedFilter(r, r, r, radius, epsilon, multithread, radius / 2); + guidedFilter(g, g, g, radius, epsilon, multithread, radius / 2); + guidedFilter(b, b, b, radius, epsilon, multithread, radius / 2); } + } // namespace @@ -309,31 +230,33 @@ void ImProcFunctions::dehaze(Imagefloat *img) std::cout << "dehaze: strength = " << strength << std::endl; } - TMatrix ws = ICCStore::getInstance()->workingSpaceMatrix(params->icm.workingProfile); - array2D Y(W, H); - get_luminance(img, Y, ws, multiThread); - - array2D R(W, H); - array2D G(W, H); - array2D B(W, H); - int patchsize = max(int(20 / scale), 2); - extract_channels(img, Y, R, G, B, patchsize, 1e-1, multiThread); - array2D dark(W, H); - patchsize = std::max(W / (200 + params->dehaze.detail * (SGN(params->dehaze.detail) > 0 ? 4 : 1)), 2); - int npatches = get_dark_channel(R, G, B, dark, patchsize, nullptr, multiThread); - DEBUG_DUMP(dark); + int patchsize = max(int(5 / scale), 2); + int npatches = 0; float ambient[3]; - int n = estimate_ambient_light(R, G, B, dark, Y, patchsize, npatches, ambient); - float ambient_Y = Color::rgbLuminance(ambient[0], ambient[1], ambient[2], ws); + array2D &t_tilde = dark; + float max_t = 0.f; - if (options.rtSettings.verbose) { - std::cout << "dehaze: ambient light is " - << ambient[0] << ", " << ambient[1] << ", " << ambient[2] - << " (average of " << n << ")" - << std::endl; - std::cout << " ambient luminance is " << ambient_Y << std::endl; + { + array2D R(W, H); + array2D G(W, H); + array2D B(W, H); + extract_channels(img, R, G, B, patchsize, 1e-1, multiThread); + + patchsize = max(max(W, H) / 600, 2); + npatches = get_dark_channel(R, G, B, dark, patchsize, nullptr, multiThread); + DEBUG_DUMP(dark); + + max_t = estimate_ambient_light(R, G, B, dark, patchsize, npatches, ambient); + + if (options.rtSettings.verbose) { + std::cout << "dehaze: ambient light is " + << ambient[0] << ", " << ambient[1] << ", " << ambient[2] + << std::endl; + } + + get_dark_channel(R, G, B, dark, patchsize, ambient, multiThread); } if (min(ambient[0], ambient[1], ambient[2]) < 0.01f) { @@ -344,59 +267,41 @@ void ImProcFunctions::dehaze(Imagefloat *img) return; // probably no haze at all } - array2D &t_tilde = dark; - get_dark_channel(R, G, B, dark, patchsize, ambient, multiThread); - apply_contrast(dark, ambient_Y, params->dehaze.depth, scale, multiThread); DEBUG_DUMP(t_tilde); - if (!params->dehaze.showDepthMap) { -#ifdef _OPENMP - #pragma omp parallel for if (multiThread) -#endif - for (int y = 0; y < H; ++y) { - for (int x = 0; x < W; ++x) { - dark[y][x] = 1.f - strength * dark[y][x]; - } - } - } - - float mult = 2.f; - if (params->dehaze.detail > 0) { - mult -= (params->dehaze.detail / 100.f) * 1.9f; - } else { - mult -= params->dehaze.detail / 10.f; - } - const int radius = max(int(patchsize * mult), 1); - const float epsilon = 2.5e-4; - array2D &t = t_tilde; - - if (!params->dehaze.showDepthMap) - guidedFilter(Y, t_tilde, t, radius, epsilon, multiThread); - - DEBUG_DUMP(t); - - - if (params->dehaze.showDepthMap) { -#ifdef _OPENMP - #pragma omp parallel for if (multiThread) -#endif - for (int y = 0; y < H; ++y) { - for (int x = 0; x < W; ++x) { - img->r(y, x) = img->g(y, x) = img->b(y, x) = t[y][x] * 65535.f; - } - } - return; - } - - const float t0 = 0.1; - const float teps = 1e-3; #ifdef _OPENMP #pragma omp parallel for if (multiThread) #endif for (int y = 0; y < H; ++y) { for (int x = 0; x < W; ++x) { + dark[y][x] = 1.f - strength * dark[y][x]; + } + } + + const int radius = patchsize * 4; + const float epsilon = 1e-7; + array2D &t = t_tilde; + + { + array2D guideB(W, H, img->b.ptrs, ARRAY2D_BYREFERENCE); + guidedFilter(guideB, t_tilde, t, radius, epsilon, multiThread, patchsize); + } + + DEBUG_DUMP(t); + + float depth = -float(params->dehaze.depth) / 100.f; + const float t0 = max(1e-3f, std::exp(depth * max_t)); + const float teps = 1e-3f; +#ifdef _OPENMP + #pragma omp parallel for if (multiThread) +#endif + for (int y = 0; y < H; ++y) { + for (int x = 0; x < W; ++x) { + // ensure that the transmission is such that to avoid clipping... float rgb[3] = { img->r(y, x), img->g(y, x), img->b(y, x) }; + // ... t >= tl to avoid negative values float tl = 1.f - min(rgb[0]/ambient[0], rgb[1]/ambient[1], rgb[2]/ambient[2]); + // ... t >= tu to avoid values > 1 float tu = t0 - teps; for (int c = 0; c < 3; ++c) { if (ambient[c] < 1) { @@ -404,44 +309,21 @@ void ImProcFunctions::dehaze(Imagefloat *img) } } float mt = max(t[y][x], t0, tl + teps, tu + teps); - float r = (rgb[0] - ambient[0]) / mt + ambient[0]; - float g = (rgb[1] - ambient[1]) / mt + ambient[1]; - float b = (rgb[2] - ambient[2]) / mt + ambient[2]; + if (params->dehaze.showDepthMap) { + img->r(y, x) = img->g(y, x) = img->b(y, x) = 1.f - mt; + } else { + float r = (rgb[0] - ambient[0]) / mt + ambient[0]; + float g = (rgb[1] - ambient[1]) / mt + ambient[1]; + float b = (rgb[2] - ambient[2]) / mt + ambient[2]; - img->r(y, x) = r; - img->g(y, x) = g; - img->b(y, x) = b; - } - } - - float oldmed; - findMinMaxPercentile(Y, Y.width() * Y.height(), 0.5, oldmed, 0.5, oldmed, multiThread); - - get_luminance(img, Y, ws, multiThread); - float newmed; - - findMinMaxPercentile(Y, Y.width() * Y.height(), 0.5, newmed, 0.5, newmed, multiThread); - - if (newmed > 1e-5f) { - const float f1 = oldmed / newmed; - const float f = f1 * 65535.f; -#ifdef _OPENMP - #pragma omp parallel for if (multiThread) -#endif - for (int y = 0; y < H; ++y) { - for (int x = 0; x < W; ++x) { - float r = img->r(y, x); - float g = img->g(y, x); - float b = img->b(y, x); - float h, s, l; - Color::rgb2hslfloat(r * f, g * f, b * f, h, s, l); - s = LIM01(s / f1); - Color::hsl2rgbfloat(h, s, l, img->r(y, x), img->g(y, x), img->b(y, x)); + img->r(y, x) = r; + img->g(y, x) = g; + img->b(y, x) = b; } } - } else { - img->normalizeFloatTo65535(); } + + img->normalizeFloatTo65535(); } diff --git a/rtengine/procparams.cc b/rtengine/procparams.cc index 17afb3371..78ee78f45 100644 --- a/rtengine/procparams.cc +++ b/rtengine/procparams.cc @@ -2378,8 +2378,7 @@ DehazeParams::DehazeParams() : enabled(false), strength(50), showDepthMap(false), - depth(0), - detail(0) + depth(25) { } @@ -2389,8 +2388,7 @@ bool DehazeParams::operator ==(const DehazeParams& other) const enabled == other.enabled && strength == other.strength && showDepthMap == other.showDepthMap - && depth == other.depth - && detail == other.detail; + && depth == other.depth; } bool DehazeParams::operator !=(const DehazeParams& other) const @@ -3070,7 +3068,6 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo saveToKeyfile(!pedited || pedited->dehaze.strength, "Dehaze", "Strength", dehaze.strength, keyFile); saveToKeyfile(!pedited || pedited->dehaze.showDepthMap, "Dehaze", "ShowDepthMap", dehaze.showDepthMap, keyFile); saveToKeyfile(!pedited || pedited->dehaze.depth, "Dehaze", "Depth", dehaze.depth, keyFile); - saveToKeyfile(!pedited || pedited->dehaze.detail, "Dehaze", "Detail", dehaze.detail, keyFile); // Directional pyramid denoising saveToKeyfile(!pedited || pedited->dirpyrDenoise.enabled, "Directional Pyramid Denoising", "Enabled", dirpyrDenoise.enabled, keyFile); @@ -4658,7 +4655,6 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited) assignFromKeyfile(keyFile, "Dehaze", "Strength", pedited, dehaze.strength, pedited->dehaze.strength); assignFromKeyfile(keyFile, "Dehaze", "ShowDepthMap", pedited, dehaze.showDepthMap, pedited->dehaze.showDepthMap); assignFromKeyfile(keyFile, "Dehaze", "Depth", pedited, dehaze.depth, pedited->dehaze.depth); - assignFromKeyfile(keyFile, "Dehaze", "Detail", pedited, dehaze.detail, pedited->dehaze.detail); } if (keyFile.has_group("Film Simulation")) { diff --git a/rtengine/procparams.h b/rtengine/procparams.h index 143fedbe8..d335ad029 100644 --- a/rtengine/procparams.h +++ b/rtengine/procparams.h @@ -1232,7 +1232,6 @@ struct DehazeParams { int strength; bool showDepthMap; int depth; - int detail; DehazeParams(); diff --git a/rtgui/dehaze.cc b/rtgui/dehaze.cc index ef5075ab7..0f0892ac6 100644 --- a/rtgui/dehaze.cc +++ b/rtgui/dehaze.cc @@ -32,27 +32,21 @@ Dehaze::Dehaze(): FoldableToolPanel(this, "dehaze", M("TP_DEHAZE_LABEL"), false, EvDehazeStrength = m->newEvent(HDR, "HISTORY_MSG_DEHAZE_STRENGTH"); EvDehazeShowDepthMap = m->newEvent(HDR, "HISTORY_MSG_DEHAZE_SHOW_DEPTH_MAP"); EvDehazeDepth = m->newEvent(HDR, "HISTORY_MSG_DEHAZE_DEPTH"); - EvDehazeDetail = m->newEvent(HDR, "HISTORY_MSG_DEHAZE_DETAIL"); strength = Gtk::manage(new Adjuster(M("TP_DEHAZE_STRENGTH"), 0., 100., 1., 50.)); strength->setAdjusterListener(this); strength->show(); - depth = Gtk::manage(new Adjuster(M("TP_DEHAZE_DEPTH"), -100., 100., 1., 0.)); + depth = Gtk::manage(new Adjuster(M("TP_DEHAZE_DEPTH"), 0., 100., 1., 25.)); depth->setAdjusterListener(this); depth->show(); - detail = Gtk::manage(new Adjuster(M("TP_DEHAZE_DETAIL"), -100, 100, 1, 0)); - detail->setAdjusterListener(this); - detail->show(); - showDepthMap = Gtk::manage(new Gtk::CheckButton(M("TP_DEHAZE_SHOW_DEPTH_MAP"))); showDepthMap->signal_toggled().connect(sigc::mem_fun(*this, &Dehaze::showDepthMapChanged)); showDepthMap->show(); pack_start(*strength); pack_start(*depth); - pack_start(*detail); pack_start(*showDepthMap); } @@ -64,7 +58,6 @@ void Dehaze::read(const ProcParams *pp, const ParamsEdited *pedited) if (pedited) { strength->setEditedState(pedited->dehaze.strength ? Edited : UnEdited); depth->setEditedState(pedited->dehaze.depth ? Edited : UnEdited); - detail->setEditedState(pedited->dehaze.detail ? Edited : UnEdited); set_inconsistent(multiImage && !pedited->dehaze.enabled); showDepthMap->set_inconsistent(!pedited->dehaze.showDepthMap); } @@ -72,7 +65,6 @@ void Dehaze::read(const ProcParams *pp, const ParamsEdited *pedited) setEnabled(pp->dehaze.enabled); strength->setValue(pp->dehaze.strength); depth->setValue(pp->dehaze.depth); - detail->setValue(pp->dehaze.detail); showDepthMap->set_active(pp->dehaze.showDepthMap); enableListener(); @@ -83,14 +75,12 @@ void Dehaze::write(ProcParams *pp, ParamsEdited *pedited) { pp->dehaze.strength = strength->getValue(); pp->dehaze.depth = depth->getValue(); - pp->dehaze.detail = detail->getValue(); pp->dehaze.enabled = getEnabled(); pp->dehaze.showDepthMap = showDepthMap->get_active(); if (pedited) { pedited->dehaze.strength = strength->getEditedState(); pedited->dehaze.depth = depth->getEditedState(); - pedited->dehaze.detail = detail->getEditedState(); pedited->dehaze.enabled = !get_inconsistent(); pedited->dehaze.showDepthMap = !showDepthMap->get_inconsistent(); } @@ -100,16 +90,13 @@ void Dehaze::setDefaults(const ProcParams *defParams, const ParamsEdited *pedite { strength->setDefault(defParams->dehaze.strength); depth->setDefault(defParams->dehaze.depth); - detail->setDefault(defParams->dehaze.detail); if (pedited) { strength->setDefaultEditedState(pedited->dehaze.strength ? Edited : UnEdited); depth->setDefaultEditedState(pedited->dehaze.depth ? Edited : UnEdited); - detail->setDefaultEditedState(pedited->dehaze.detail ? Edited : UnEdited); } else { strength->setDefaultEditedState(Irrelevant); depth->setDefaultEditedState(Irrelevant); - detail->setDefaultEditedState(Irrelevant); } } @@ -121,8 +108,6 @@ void Dehaze::adjusterChanged(Adjuster* a, double newval) listener->panelChanged(EvDehazeStrength, a->getTextValue()); } else if (a == depth) { listener->panelChanged(EvDehazeDepth, a->getTextValue()); - } else if (a == detail) { - listener->panelChanged(EvDehazeDetail, a->getTextValue()); } } } @@ -156,7 +141,6 @@ void Dehaze::setBatchMode(bool batchMode) strength->showEditedCB(); depth->showEditedCB(); - detail->showEditedCB(); } diff --git a/rtgui/dehaze.h b/rtgui/dehaze.h index ae6097c86..26cbef74a 100644 --- a/rtgui/dehaze.h +++ b/rtgui/dehaze.h @@ -28,13 +28,11 @@ class Dehaze: public ToolParamBlock, public AdjusterListener, public FoldableToo private: Adjuster *strength; Adjuster *depth; - Adjuster *detail; Gtk::CheckButton *showDepthMap; rtengine::ProcEvent EvDehazeEnabled; rtengine::ProcEvent EvDehazeStrength; rtengine::ProcEvent EvDehazeDepth; - rtengine::ProcEvent EvDehazeDetail; rtengine::ProcEvent EvDehazeShowDepthMap; public: diff --git a/rtgui/paramsedited.cc b/rtgui/paramsedited.cc index ffc1bd19c..610c6d3e2 100644 --- a/rtgui/paramsedited.cc +++ b/rtgui/paramsedited.cc @@ -570,7 +570,6 @@ void ParamsEdited::set(bool v) dehaze.strength = v; dehaze.showDepthMap = v; dehaze.depth = v; - dehaze.detail = v; metadata.mode = v; exif = v; @@ -1128,7 +1127,6 @@ void ParamsEdited::initFrom(const std::vector& dehaze.strength = dehaze.strength && p.dehaze.strength == other.dehaze.strength; dehaze.showDepthMap = dehaze.showDepthMap && p.dehaze.showDepthMap == other.dehaze.showDepthMap; dehaze.depth = dehaze.depth && p.dehaze.depth == other.dehaze.depth; - dehaze.detail = dehaze.detail && p.dehaze.detail == other.dehaze.detail; metadata.mode = metadata.mode && p.metadata.mode == other.metadata.mode; // How the hell can we handle that??? @@ -3135,10 +3133,6 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng toEdit.dehaze.depth = mods.dehaze.depth; } - if (dehaze.detail) { - toEdit.dehaze.detail = mods.dehaze.detail; - } - if (dehaze.showDepthMap) { toEdit.dehaze.showDepthMap = mods.dehaze.showDepthMap; } diff --git a/rtgui/paramsedited.h b/rtgui/paramsedited.h index 73a19db88..3142b0136 100644 --- a/rtgui/paramsedited.h +++ b/rtgui/paramsedited.h @@ -731,7 +731,6 @@ public: bool strength; bool showDepthMap; bool depth; - bool detail; }; From 59339644de501ce539a9d35b25ead22a7e7f5518 Mon Sep 17 00:00:00 2001 From: Alberto Griggio Date: Wed, 17 Oct 2018 15:38:35 +0200 Subject: [PATCH 09/42] dehaze: do not consider out-of-gamut pixels when estimating the ambient light --- rtengine/ipdehaze.cc | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/rtengine/ipdehaze.cc b/rtengine/ipdehaze.cc index 1c5512c2a..37bd53704 100644 --- a/rtengine/ipdehaze.cc +++ b/rtengine/ipdehaze.cc @@ -58,8 +58,7 @@ namespace { #endif -int get_dark_channel(const array2D &R, const array2D &G, const array2D &B, array2D &dst, - int patchsize, float *ambient, bool multithread) +int get_dark_channel(const array2D &R, const array2D &G, const array2D &B, array2D &dst, int patchsize, float *ambient, bool clip, bool multithread) { const int W = R.width(); const int H = R.height(); @@ -89,7 +88,9 @@ int get_dark_channel(const array2D &R, const array2D &G, const arr } val = min(val, yval); } - val = LIM01(val); + if (clip) { + val = LIM01(val); + } for (int yy = y; yy < pH; ++yy) { std::fill(dst[yy]+x, dst[yy]+pW, val); } @@ -120,7 +121,9 @@ float estimate_ambient_light(const array2D &R, const array2D &G, c std::priority_queue p; for (int y = 0; y < H; y += patchsize) { for (int x = 0; x < W; x += patchsize) { - p.push(dark[y][x]); + if (!OOG(dark[y][x], 1.f)) { + p.push(dark[y][x]); + } } } darklim = get_percentile(p, 0.95); @@ -131,7 +134,7 @@ float estimate_ambient_light(const array2D &R, const array2D &G, c for (int y = 0; y < H; y += patchsize) { for (int x = 0; x < W; x += patchsize) { - if (dark[y][x] >= darklim) { + if (dark[y][x] >= darklim && !OOG(dark[y][x], 1.f)) { patches.push_back(std::make_pair(x, y)); } } @@ -245,7 +248,7 @@ void ImProcFunctions::dehaze(Imagefloat *img) extract_channels(img, R, G, B, patchsize, 1e-1, multiThread); patchsize = max(max(W, H) / 600, 2); - npatches = get_dark_channel(R, G, B, dark, patchsize, nullptr, multiThread); + npatches = get_dark_channel(R, G, B, dark, patchsize, nullptr, false, multiThread); DEBUG_DUMP(dark); max_t = estimate_ambient_light(R, G, B, dark, patchsize, npatches, ambient); @@ -256,7 +259,7 @@ void ImProcFunctions::dehaze(Imagefloat *img) << std::endl; } - get_dark_channel(R, G, B, dark, patchsize, ambient, multiThread); + get_dark_channel(R, G, B, dark, patchsize, ambient, true, multiThread); } if (min(ambient[0], ambient[1], ambient[2]) < 0.01f) { @@ -289,6 +292,10 @@ void ImProcFunctions::dehaze(Imagefloat *img) DEBUG_DUMP(t); + if (options.rtSettings.verbose) { + std::cout << "dehaze: max distance is " << max_t << std::endl; + } + float depth = -float(params->dehaze.depth) / 100.f; const float t0 = max(1e-3f, std::exp(depth * max_t)); const float teps = 1e-3f; From 2026fe1d1715a77b94ba931a2f89c0f524fb61b9 Mon Sep 17 00:00:00 2001 From: Alberto Griggio Date: Thu, 18 Oct 2018 08:53:02 +0200 Subject: [PATCH 10/42] guided filter: added support for automatic computation of subsampling factor --- rtengine/guidedfilter.cc | 28 ++++++++++++++++++++++++++++ rtengine/guidedfilter.h | 2 +- rtengine/ipdehaze.cc | 8 ++++---- 3 files changed, 33 insertions(+), 5 deletions(-) diff --git a/rtengine/guidedfilter.cc b/rtengine/guidedfilter.cc index f6b702a73..a3dccf298 100644 --- a/rtengine/guidedfilter.cc +++ b/rtengine/guidedfilter.cc @@ -52,11 +52,39 @@ namespace rtengine { #endif +namespace { + +int calculate_subsampling(int w, int h, int r) +{ + if (r == 1) { + return 1; + } + + if (max(w, h) <= 600) { + return 1; + } + + for (int s = 5; s > 0; --s) { + if (r % s == 0) { + return s; + } + } + + return LIM(r / 2, 2, 4); +} + +} // namespace + + void guidedFilter(const array2D &guide, const array2D &src, array2D &dst, int r, float epsilon, bool multithread, int subsampling) { const int W = src.width(); const int H = src.height(); + if (subsampling <= 0) { + subsampling = calculate_subsampling(W, H, r); + } + enum Op { MUL, DIVEPSILON, ADD, SUB, ADDMUL, SUBMUL }; const auto apply = diff --git a/rtengine/guidedfilter.h b/rtengine/guidedfilter.h index 3f987f80e..6691af251 100644 --- a/rtengine/guidedfilter.h +++ b/rtengine/guidedfilter.h @@ -24,6 +24,6 @@ namespace rtengine { -void guidedFilter(const array2D &guide, const array2D &src, array2D &dst, int r, float epsilon, bool multithread, int subsampling=4); +void guidedFilter(const array2D &guide, const array2D &src, array2D &dst, int r, float epsilon, bool multithread, int subsampling=0); } // namespace rtengine diff --git a/rtengine/ipdehaze.cc b/rtengine/ipdehaze.cc index 37bd53704..92eaa4062 100644 --- a/rtengine/ipdehaze.cc +++ b/rtengine/ipdehaze.cc @@ -208,9 +208,9 @@ void extract_channels(Imagefloat *img, array2D &r, array2D &g, arr } } - guidedFilter(r, r, r, radius, epsilon, multithread, radius / 2); - guidedFilter(g, g, g, radius, epsilon, multithread, radius / 2); - guidedFilter(b, b, b, radius, epsilon, multithread, radius / 2); + guidedFilter(r, r, r, radius, epsilon, multithread); + guidedFilter(g, g, g, radius, epsilon, multithread); + guidedFilter(b, b, b, radius, epsilon, multithread); } @@ -287,7 +287,7 @@ void ImProcFunctions::dehaze(Imagefloat *img) { array2D guideB(W, H, img->b.ptrs, ARRAY2D_BYREFERENCE); - guidedFilter(guideB, t_tilde, t, radius, epsilon, multiThread, patchsize); + guidedFilter(guideB, t_tilde, t, radius, epsilon, multiThread); } DEBUG_DUMP(t); From 52c943ca0e5edfcbd82207a99593ae603654f3f2 Mon Sep 17 00:00:00 2001 From: George Hilliard Date: Fri, 26 Oct 2018 00:20:02 -0500 Subject: [PATCH 11/42] Mark BatchQueuePanel implementation functions as private --- rtgui/batchqueuepanel.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/rtgui/batchqueuepanel.h b/rtgui/batchqueuepanel.h index 3f1da85ce..73cb3ba6e 100644 --- a/rtgui/batchqueuepanel.h +++ b/rtgui/batchqueuepanel.h @@ -60,22 +60,23 @@ public: void init (RTWindow* parent); void addBatchQueueJobs(const std::vector& entries , bool head = false); + void saveOptions (); + + bool handleShortcutKey (GdkEventKey* event); // batchqueuelistener interface void queueSizeChanged(int qsize, bool queueEmptied, bool queueError, const Glib::ustring& queueErrorMessage); bool canStartNext(); +private: void startBatchProc (); void stopBatchProc (); void startOrStopBatchProc(); - void saveOptions (); void pathFolderChanged (); void pathFolderButtonPressed (); void formatChanged(const Glib::ustring& format) override; void updateTab (int qsize, int forceOrientation = 0); // forceOrientation=0: base on options / 1: horizontal / 2: vertical - - bool handleShortcutKey (GdkEventKey* event); }; #endif From 7d5fe6d1c8c9e681e64522544055089933e4d2d6 Mon Sep 17 00:00:00 2001 From: George Hilliard Date: Fri, 26 Oct 2018 00:52:15 -0500 Subject: [PATCH 12/42] Reenable batch queue interface on queue length notification This removes the need for canStartNext() to do any UI updates. --- rtgui/batchqueue.cc | 24 +++++++++++------------- rtgui/batchqueue.h | 4 ++-- rtgui/batchqueuepanel.cc | 8 +++++--- 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/rtgui/batchqueue.cc b/rtgui/batchqueue.cc index 1d52c96e6..191131352 100644 --- a/rtgui/batchqueue.cc +++ b/rtgui/batchqueue.cc @@ -45,7 +45,7 @@ namespace struct NLParams { BatchQueueListener* listener; int qsize; - bool queueEmptied; + bool queueRunning; bool queueError; Glib::ustring queueErrorMessage; }; @@ -53,7 +53,7 @@ struct NLParams { int bqnotifylistenerUI (void* data) { NLParams* params = static_cast(data); - params->listener->queueSizeChanged (params->qsize, params->queueEmptied, params->queueError, params->queueErrorMessage); + params->listener->queueSizeChanged (params->qsize, params->queueRunning, params->queueError, params->queueErrorMessage); delete params; return 0; } @@ -229,7 +229,7 @@ void BatchQueue::addEntries (const std::vector& entries, bool saveBatchQueue (); redraw (); - notifyListener (false); + notifyListener (true); } bool BatchQueue::saveBatchQueue () @@ -387,7 +387,7 @@ bool BatchQueue::loadBatchQueue () } redraw (); - notifyListener (false); + notifyListener (true); return !fd.empty (); } @@ -460,7 +460,7 @@ void BatchQueue::cancelItems (const std::vector& items) saveBatchQueue (); redraw (); - notifyListener (false); + notifyListener (true); } void BatchQueue::headItems (const std::vector& items) @@ -640,7 +640,7 @@ void BatchQueue::error(const Glib::ustring& descr) if (listener) { NLParams* params = new NLParams; params->listener = listener; - params->queueEmptied = false; + params->queueRunning = false; params->queueError = true; params->queueErrorMessage = descr; idle_register.add(bqnotifylistenerUI, params); @@ -706,7 +706,6 @@ rtengine::ProcessingJob* BatchQueue::imageReady(rtengine::IImagefloat* img) Glib::ustring processedParams = processing->savedParamsFile; // delete from the queue - bool queueEmptied = false; bool remove_button_set = false; { @@ -718,9 +717,7 @@ rtengine::ProcessingJob* BatchQueue::imageReady(rtengine::IImagefloat* img) fd.erase (fd.begin()); // return next job - if (fd.empty()) { - queueEmptied = true; - } else if (listener && listener->canStartNext ()) { + if (!fd.empty() && listener && listener->canStartNext ()) { BatchQueueEntry* next = static_cast(fd[0]); // tag it as selected and set sequence next->processing = true; @@ -778,7 +775,8 @@ rtengine::ProcessingJob* BatchQueue::imageReady(rtengine::IImagefloat* img) } redraw (); - notifyListener (queueEmptied); + const bool queueRunning = (processing != nullptr); + notifyListener (queueRunning); return processing ? processing->job : nullptr; } @@ -973,7 +971,7 @@ void BatchQueue::buttonPressed (LWButton* button, int actionCode, void* actionDa } } -void BatchQueue::notifyListener (bool queueEmptied) +void BatchQueue::notifyListener (bool queueRunning) { if (listener) { @@ -983,7 +981,7 @@ void BatchQueue::notifyListener (bool queueEmptied) MYREADERLOCK(l, entryRW); params->qsize = fd.size(); } - params->queueEmptied = queueEmptied; + params->queueRunning = queueRunning; params->queueError = false; idle_register.add(bqnotifylistenerUI, params); } diff --git a/rtgui/batchqueue.h b/rtgui/batchqueue.h index 41c30da3f..6b0e047cb 100644 --- a/rtgui/batchqueue.h +++ b/rtgui/batchqueue.h @@ -31,7 +31,7 @@ class BatchQueueListener public: virtual ~BatchQueueListener() = default; - virtual void queueSizeChanged(int qsize, bool queueEmptied, bool queueError, const Glib::ustring& queueErrorMessage) = 0; + virtual void queueSizeChanged(int qsize, bool queueRunning, bool queueError, const Glib::ustring& queueErrorMessage) = 0; virtual bool canStartNext() = 0; }; @@ -93,7 +93,7 @@ protected: Glib::ustring autoCompleteFileName (const Glib::ustring& fileName, const Glib::ustring& format); Glib::ustring getTempFilenameForParams( const Glib::ustring &filename ); bool saveBatchQueue (); - void notifyListener (bool queueEmptied); + void notifyListener (bool queueRunning); BatchQueueEntry* processing; // holds the currently processed image FileCatalog* fileCatalog; diff --git a/rtgui/batchqueuepanel.cc b/rtgui/batchqueuepanel.cc index 83a0f37ae..f572a6772 100644 --- a/rtgui/batchqueuepanel.cc +++ b/rtgui/batchqueuepanel.cc @@ -245,7 +245,7 @@ void BatchQueuePanel::updateTab (int qsize, int forceOrientation) } } -void BatchQueuePanel::queueSizeChanged(int qsize, bool queueEmptied, bool queueError, const Glib::ustring& queueErrorMessage) +void BatchQueuePanel::queueSizeChanged(int qsize, bool queueRunning, bool queueError, const Glib::ustring& queueErrorMessage) { updateTab (qsize); @@ -255,12 +255,14 @@ void BatchQueuePanel::queueSizeChanged(int qsize, bool queueEmptied, bool queueE qStartStop->set_sensitive(true); } - if (queueEmptied || queueError) { + if (!queueRunning) { stopBatchProc (); fdir->set_sensitive (true); fformat->set_sensitive (true); - SoundManager::playSoundAsync(options.sndBatchQueueDone); + if (qsize == 0) { + SoundManager::playSoundAsync(options.sndBatchQueueDone); + } } if (queueError) { From 09275b58269b3f3be6c53f600ada5c1cf488ca33 Mon Sep 17 00:00:00 2001 From: George Hilliard Date: Fri, 26 Oct 2018 00:53:39 -0500 Subject: [PATCH 13/42] Store qStartStop state in atomic for background thread Closes #4882. --- rtgui/batchqueuepanel.cc | 13 +++++-------- rtgui/batchqueuepanel.h | 4 ++++ 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/rtgui/batchqueuepanel.cc b/rtgui/batchqueuepanel.cc index f572a6772..b61f60ee7 100644 --- a/rtgui/batchqueuepanel.cc +++ b/rtgui/batchqueuepanel.cc @@ -286,6 +286,7 @@ void BatchQueuePanel::startBatchProc () // Update switch when queue started programmatically qStartStopConn.block (true); qStartStop->set_active(true); + qStartStopState = true; qStartStopConn.block (false); if (batchQueue->hasJobs()) { @@ -308,6 +309,7 @@ void BatchQueuePanel::stopBatchProc () // Update switch when queue started programmatically qStartStopConn.block (true); qStartStop->set_active(false); + qStartStopState = false; qStartStopConn.block (false); updateTab (batchQueue->getEntries().size()); @@ -324,14 +326,9 @@ void BatchQueuePanel::addBatchQueueJobs(const std::vector& ent bool BatchQueuePanel::canStartNext () { -// GThreadLock lock; - if (qStartStop->get_active()) { - return true; - } else { - fdir->set_sensitive (true); - fformat->set_sensitive (true); - return false; - } + // This function is called from the background BatchQueue thread. + // It cannot call UI functions, so grab the stored state of qStartStop. + return qStartStopState; } void BatchQueuePanel::saveOptions () diff --git a/rtgui/batchqueuepanel.h b/rtgui/batchqueuepanel.h index 73cb3ba6e..89b8d8910 100644 --- a/rtgui/batchqueuepanel.h +++ b/rtgui/batchqueuepanel.h @@ -19,6 +19,8 @@ #ifndef _BATCHQUEUEPANEL_ #define _BATCHQUEUEPANEL_ +#include + #include #include "batchqueue.h" #include "saveformatpanel.h" @@ -53,6 +55,8 @@ class BatchQueuePanel : public Gtk::VBox, IdleRegister idle_register; + std::atomic qStartStopState; + public: explicit BatchQueuePanel (FileCatalog* aFileCatalog); ~BatchQueuePanel(); From 8a6e0a7f1929839ef36e3c63d1f43680c8b17bad Mon Sep 17 00:00:00 2001 From: George Hilliard Date: Fri, 26 Oct 2018 01:46:30 -0500 Subject: [PATCH 14/42] Cleanup from code review --- rtgui/batchqueue.cc | 2 +- rtgui/batchqueuepanel.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/rtgui/batchqueue.cc b/rtgui/batchqueue.cc index 191131352..a66fda153 100644 --- a/rtgui/batchqueue.cc +++ b/rtgui/batchqueue.cc @@ -775,7 +775,7 @@ rtengine::ProcessingJob* BatchQueue::imageReady(rtengine::IImagefloat* img) } redraw (); - const bool queueRunning = (processing != nullptr); + const bool queueRunning = processing; notifyListener (queueRunning); return processing ? processing->job : nullptr; diff --git a/rtgui/batchqueuepanel.h b/rtgui/batchqueuepanel.h index 89b8d8910..a05d94fe3 100644 --- a/rtgui/batchqueuepanel.h +++ b/rtgui/batchqueuepanel.h @@ -53,10 +53,10 @@ class BatchQueuePanel : public Gtk::VBox, Gtk::HBox* bottomBox; Gtk::HBox* topBox; - IdleRegister idle_register; - std::atomic qStartStopState; + IdleRegister idle_register; + public: explicit BatchQueuePanel (FileCatalog* aFileCatalog); ~BatchQueuePanel(); From b37d88fb2245fc99c529a377c57f3475c9da3c54 Mon Sep 17 00:00:00 2001 From: heckflosse Date: Fri, 26 Oct 2018 14:43:36 +0200 Subject: [PATCH 15/42] Always use auto-contrast threshold when using Amaze+VNG4 as demosaicer for motion areas in pixelshift --- rtengine/pixelshift.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/rtengine/pixelshift.cc b/rtengine/pixelshift.cc index cdf4f990a..76d1f836c 100644 --- a/rtengine/pixelshift.cc +++ b/rtengine/pixelshift.cc @@ -326,7 +326,7 @@ BENCHFUN if (bayerParams.pixelShiftDemosaicMethod == bayerParams.getPSDemosaicMethodString(RAWParams::BayerSensor::PSDemosaicMethod::LMMSE)) { lmmse_interpolate_omp(winw, winh, *(rawDataFrames[0]), red, green, blue, bayerParams.lmmse_iterations); } else if (bayerParams.pixelShiftDemosaicMethod == bayerParams.getPSDemosaicMethodString(RAWParams::BayerSensor::PSDemosaicMethod::AMAZEVNG4)) { - dual_demosaic_RT (true, rawParamsIn, winw, winh, *(rawDataFrames[0]), red, green, blue, bayerParams.dualDemosaicContrast); + dual_demosaic_RT (true, rawParamsIn, winw, winh, *(rawDataFrames[0]), red, green, blue, bayerParams.dualDemosaicContrast, true); } else { amaze_demosaic_RT(winx, winy, winw, winh, *(rawDataFrames[0]), red, green, blue); } @@ -338,7 +338,7 @@ BENCHFUN if (bayerParams.pixelShiftDemosaicMethod == bayerParams.getPSDemosaicMethodString(RAWParams::BayerSensor::PSDemosaicMethod::LMMSE)) { lmmse_interpolate_omp(winw, winh, *(rawDataFrames[i + 1]), redTmp[i], greenTmp[i], blueTmp[i], bayerParams.lmmse_iterations); } else if (bayerParams.pixelShiftDemosaicMethod == bayerParams.getPSDemosaicMethodString(RAWParams::BayerSensor::PSDemosaicMethod::AMAZEVNG4)) { - dual_demosaic_RT (true, rawParamsIn, winw, winh, *(rawDataFrames[i + 1]), redTmp[i], greenTmp[i], blueTmp[i], bayerParams.dualDemosaicContrast); + dual_demosaic_RT (true, rawParamsIn, winw, winh, *(rawDataFrames[i + 1]), redTmp[i], greenTmp[i], blueTmp[i], bayerParams.dualDemosaicContrast, true); } else { amaze_demosaic_RT(winx, winy, winw, winh, *(rawDataFrames[i + 1]), redTmp[i], greenTmp[i], blueTmp[i]); } @@ -367,7 +367,7 @@ BENCHFUN } else if (bayerParams.pixelShiftDemosaicMethod == bayerParams.getPSDemosaicMethodString(RAWParams::BayerSensor::PSDemosaicMethod::AMAZEVNG4)) { RAWParams rawParamsTmp = rawParamsIn; rawParamsTmp.bayersensor.method = RAWParams::BayerSensor::getMethodString(RAWParams::BayerSensor::Method::AMAZEVNG4); - dual_demosaic_RT (true, rawParamsTmp, winw, winh, rawData, red, green, blue, bayerParams.dualDemosaicContrast); + dual_demosaic_RT (true, rawParamsTmp, winw, winh, rawData, red, green, blue, bayerParams.dualDemosaicContrast, true); } else { amaze_demosaic_RT(winx, winy, winw, winh, rawData, red, green, blue); } From cb3cc6cad14b6229564f7efcac252b94495aa15d Mon Sep 17 00:00:00 2001 From: George Hilliard Date: Fri, 26 Oct 2018 09:23:46 -0500 Subject: [PATCH 16/42] Fix permanently disabled button when stopping on next-to-last image --- rtgui/batchqueuepanel.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rtgui/batchqueuepanel.cc b/rtgui/batchqueuepanel.cc index b61f60ee7..1679d9365 100644 --- a/rtgui/batchqueuepanel.cc +++ b/rtgui/batchqueuepanel.cc @@ -249,7 +249,7 @@ void BatchQueuePanel::queueSizeChanged(int qsize, bool queueRunning, bool queueE { updateTab (qsize); - if (qsize == 0 || (qsize == 1 && !fdir->get_sensitive())) { + if (qsize == 0 || (qsize == 1 && queueRunning)) { qStartStop->set_sensitive(false); } else { qStartStop->set_sensitive(true); From 9a22e89125c4c9548fd7c5273fb88e1d393d77a9 Mon Sep 17 00:00:00 2001 From: George Hilliard Date: Fri, 26 Oct 2018 09:26:18 -0500 Subject: [PATCH 17/42] Cleanup: make impl function order match header, fix declaration var name --- rtgui/batchqueuepanel.cc | 54 ++++++++++++++++++++-------------------- rtgui/batchqueuepanel.h | 2 +- 2 files changed, 28 insertions(+), 28 deletions(-) diff --git a/rtgui/batchqueuepanel.cc b/rtgui/batchqueuepanel.cc index 1679d9365..8da66183a 100644 --- a/rtgui/batchqueuepanel.cc +++ b/rtgui/batchqueuepanel.cc @@ -324,13 +324,6 @@ void BatchQueuePanel::addBatchQueueJobs(const std::vector& ent } } -bool BatchQueuePanel::canStartNext () -{ - // This function is called from the background BatchQueue thread. - // It cannot call UI functions, so grab the stored state of qStartStop. - return qStartStopState; -} - void BatchQueuePanel::saveOptions () { @@ -339,6 +332,33 @@ void BatchQueuePanel::saveOptions () options.procQueueEnabled = qAutoStart->get_active(); } +bool BatchQueuePanel::handleShortcutKey (GdkEventKey* event) +{ + bool ctrl = event->state & GDK_CONTROL_MASK; + + if (ctrl) { + switch(event->keyval) { + case GDK_KEY_s: + if (qStartStop->get_active()) { + stopBatchProc(); + } else { + startBatchProc(); + } + + return true; + } + } + + return batchQueue->keyPressed (event); +} + +bool BatchQueuePanel::canStartNext () +{ + // This function is called from the background BatchQueue thread. + // It cannot call UI functions, so grab the stored state of qStartStop. + return qStartStopState; +} + void BatchQueuePanel::pathFolderButtonPressed () { @@ -368,23 +388,3 @@ void BatchQueuePanel::formatChanged(const Glib::ustring& format) { options.saveFormatBatch = saveFormatPanel->getFormat(); } - -bool BatchQueuePanel::handleShortcutKey (GdkEventKey* event) -{ - bool ctrl = event->state & GDK_CONTROL_MASK; - - if (ctrl) { - switch(event->keyval) { - case GDK_KEY_s: - if (qStartStop->get_active()) { - stopBatchProc(); - } else { - startBatchProc(); - } - - return true; - } - } - - return batchQueue->keyPressed (event); -} diff --git a/rtgui/batchqueuepanel.h b/rtgui/batchqueuepanel.h index a05d94fe3..74c9750e7 100644 --- a/rtgui/batchqueuepanel.h +++ b/rtgui/batchqueuepanel.h @@ -69,7 +69,7 @@ public: bool handleShortcutKey (GdkEventKey* event); // batchqueuelistener interface - void queueSizeChanged(int qsize, bool queueEmptied, bool queueError, const Glib::ustring& queueErrorMessage); + void queueSizeChanged(int qsize, bool queueRunning, bool queueError, const Glib::ustring& queueErrorMessage); bool canStartNext(); private: From a5f42c238a7da14c8651617bf0155342d381f975 Mon Sep 17 00:00:00 2001 From: TooWaBoo Date: Fri, 26 Oct 2018 16:28:50 +0200 Subject: [PATCH 18/42] Update TooWaBlue-GTK3-20_.css Changes for "resizing to physical dimensions" --- rtdata/themes/TooWaBlue-GTK3-20_.css | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/rtdata/themes/TooWaBlue-GTK3-20_.css b/rtdata/themes/TooWaBlue-GTK3-20_.css index aa753727d..041b342e3 100644 --- a/rtdata/themes/TooWaBlue-GTK3-20_.css +++ b/rtdata/themes/TooWaBlue-GTK3-20_.css @@ -2,7 +2,7 @@ This file is part of RawTherapee. Copyright (c) 2016-2018 TooWaBoo - Version 2.82 + Version 2.83 RawTherapee is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -135,6 +135,18 @@ tooltip { tooltip label { color: @text-tooltip; } +.grid-spacing > * { + margin-top: 0.166666666666666666em; + margin-bottom: 0.166666666666666666em; +} +.grid-spacing > label:not(:first-child) { + margin-left: 0.75em; + margin-right: 0.25em; +} +.grid-spacing > label:first-child { + margin-left: 0; + margin-right: 0.25em; +} paned { background-color: @bg-light-grey; @@ -1999,7 +2011,7 @@ entry { } spinbutton { - margin: 0.083333333333333333em 0; + margin: 0.083333333333333333em 0 0.083333333333333333em 0.166666666666666666em; padding: 0; min-height: 1.666666666666666666em; min-width: 0; @@ -2010,7 +2022,7 @@ spinbutton { } #MyExpander spinbutton { - margin: 0.166666666666666666em 0; + margin: 0.083333333333333333em 0 0.083333333333333333em 0.166666666666666666em; padding: 0; min-height: 1.333333333333333333em; min-width: 0; From d53e44d45bd72d2a2492816532e1410385188d9d Mon Sep 17 00:00:00 2001 From: heckflosse Date: Fri, 26 Oct 2018 16:51:05 +0200 Subject: [PATCH 19/42] vng4 demosaic: precalculate weight --- rtengine/vng4_demosaic_RT.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/rtengine/vng4_demosaic_RT.cc b/rtengine/vng4_demosaic_RT.cc index 8ed05dd09..241c05507 100644 --- a/rtengine/vng4_demosaic_RT.cc +++ b/rtengine/vng4_demosaic_RT.cc @@ -24,7 +24,7 @@ #include "rawimagesource.h" #include "rawimagesource_i.h" #include "../rtgui/multilangmgr.h" -//#define BENCHMARK +#define BENCHMARK #include "StopWatch.h" namespace rtengine @@ -176,7 +176,7 @@ void RawImageSource::vng4_demosaic (const array2D &rawData, array2D &rawData, array2D Date: Fri, 26 Oct 2018 17:09:28 +0200 Subject: [PATCH 20/42] vng4 demosaic: move red/blue interpolation inside main loop for better cache usage, #4633 --- rtengine/vng4_demosaic_RT.cc | 47 ++++++++++++++++++++++-------------- 1 file changed, 29 insertions(+), 18 deletions(-) diff --git a/rtengine/vng4_demosaic_RT.cc b/rtengine/vng4_demosaic_RT.cc index 241c05507..62f5018c5 100644 --- a/rtengine/vng4_demosaic_RT.cc +++ b/rtengine/vng4_demosaic_RT.cc @@ -215,11 +215,18 @@ void RawImageSource::vng4_demosaic (const array2D &rawData, array2D &rawData, array2D firstRow) { + interpolate_row_rb_mul_pp (rawData, red[row - 1], blue[row - 1], green[row - 2], green[row - 1], green[row], row - 1, 1.0, 1.0, 1.0, 0, W, 1); + } if(plistenerActive) { if((row % progressStep) == 0) @@ -311,6 +321,24 @@ void RawImageSource::vng4_demosaic (const array2D &rawData, array2D &rawData, array2DsetProgress (0.98); } - // Interpolate R and B -#ifdef _OPENMP - #pragma omp parallel for -#endif - - for (int i = 0; i < H; i++) { - if (i == 0) - // rm, gm, bm must be recovered - //interpolate_row_rb_mul_pp (red, blue, NULL, green[i], green[i+1], i, rm, gm, bm, 0, W, 1); - { - interpolate_row_rb_mul_pp (rawData, red[i], blue[i], nullptr, green[i], green[i + 1], i, 1.0, 1.0, 1.0, 0, W, 1); - } else if (i == H - 1) { - interpolate_row_rb_mul_pp (rawData, red[i], blue[i], green[i - 1], green[i], nullptr, i, 1.0, 1.0, 1.0, 0, W, 1); - } else { - interpolate_row_rb_mul_pp (rawData, red[i], blue[i], green[i - 1], green[i], green[i + 1], i, 1.0, 1.0, 1.0, 0, W, 1); - } - } border_interpolate2(W, H, 3, rawData, red, green, blue); if(plistenerActive) { From c4ee5e611d22e1ec9721c6573689f5e21647da9c Mon Sep 17 00:00:00 2001 From: Alberto Griggio Date: Fri, 26 Oct 2018 18:04:07 +0200 Subject: [PATCH 21/42] guided filter: reuse buffer across boxblur invocations --- rtengine/guidedfilter.cc | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/rtengine/guidedfilter.cc b/rtengine/guidedfilter.cc index a3dccf298..4e31fa300 100644 --- a/rtengine/guidedfilter.cc +++ b/rtengine/guidedfilter.cc @@ -135,11 +135,14 @@ void guidedFilter(const array2D &guide, const array2D &src, array2 const array2D &p = src; array2D &q = dst; + AlignedBuffer blur_buf(I.width() * I.height()); const auto f_mean = - [](array2D &d, array2D &s, int rad) -> void + [&](array2D &d, array2D &s, int rad) -> void { rad = LIM(rad, 0, (min(s.width(), s.height()) - 1) / 2 - 1); - boxblur(s, d, rad, rad, s.width(), s.height()); + float **src = s; + float **dst = d; + boxblur(src, dst, blur_buf.data, rad, rad, s.width(), s.height()); }; const auto f_subsample = From 3d61eca91f648c8c09f2ad7b62bcdfa69ae39831 Mon Sep 17 00:00:00 2001 From: heckflosse Date: Fri, 26 Oct 2018 20:23:27 +0200 Subject: [PATCH 22/42] vng4 demosaic: remove unreachable code, #4633 --- rtengine/vng4_demosaic_RT.cc | 55 ++++++++++++------------------------ 1 file changed, 18 insertions(+), 37 deletions(-) diff --git a/rtengine/vng4_demosaic_RT.cc b/rtengine/vng4_demosaic_RT.cc index 62f5018c5..0e7d8e0f9 100644 --- a/rtengine/vng4_demosaic_RT.cc +++ b/rtengine/vng4_demosaic_RT.cc @@ -71,9 +71,8 @@ void RawImageSource::vng4_demosaic (const array2D &rawData, array2Dprefilters; const int width = W, height = H; constexpr unsigned int colors = 4; - float (*image)[4]; - image = (float (*)[4]) calloc (height * width, sizeof * image); + float (*image)[4] = (float (*)[4]) calloc (height * width, sizeof * image); #ifdef _OPENMP #pragma omp parallel for @@ -87,7 +86,7 @@ void RawImageSource::vng4_demosaic (const array2D &rawData, array2D &rawData, array2D &rawData, array2D &rawData, array2D &rawData, array2D gval[g]) { - gmin = gval[g]; - } - - if (gmax < gval[g]) { - gmax = gval[g]; - } + gmin = std::min(gmin, gval[g]); + gmax = std::max(gmax, gval[g]); } thold = gmin + (gmax / 2); } memset (sum, 0, sizeof sum); - float t1, t2; - t1 = t2 = pix[color]; + float t1p2 = pix[color]; if(color & 1) { int num = 0; @@ -273,7 +266,7 @@ void RawImageSource::vng4_demosaic (const array2D &rawData, array2D &rawData, array2D &rawData, array2D firstRow) { @@ -321,23 +313,12 @@ void RawImageSource::vng4_demosaic (const array2D &rawData, array2D 2 && firstRow < H - 3) { + interpolate_row_rb_mul_pp (rawData, red[firstRow], blue[firstRow], green[firstRow - 1], green[firstRow], green[firstRow + 1], firstRow, 1.0, 1.0, 1.0, 0, W, 1); } - if (lastRow != -1) { - if (lastRow == 0) { - interpolate_row_rb_mul_pp (rawData, red[0], blue[0], nullptr, green[0], green[1], 0, 1.0, 1.0, 1.0, 0, W, 1); - } else if (lastRow == H - 1) { - interpolate_row_rb_mul_pp (rawData, red[lastRow], blue[lastRow], green[lastRow - 1], green[lastRow], nullptr, lastRow, 1.0, 1.0, 1.0, 0, W, 1); - } else { - interpolate_row_rb_mul_pp (rawData, red[lastRow], blue[lastRow], green[lastRow - 1], green[lastRow], green[lastRow + 1], lastRow, 1.0, 1.0, 1.0, 0, W, 1); - } + + if (lastRow > 2 && lastRow < H - 3) { + interpolate_row_rb_mul_pp (rawData, red[lastRow], blue[lastRow], green[lastRow - 1], green[lastRow], green[lastRow + 1], lastRow, 1.0, 1.0, 1.0, 0, W, 1); } } free (code[0][0]); From 1b291aee9bdbed9520f394747a6cffa42932a218 Mon Sep 17 00:00:00 2001 From: heckflosse Date: Fri, 26 Oct 2018 22:20:20 +0200 Subject: [PATCH 23/42] vng4 demosaic: minor speedup, #4633 --- rtengine/vng4_demosaic_RT.cc | 46 ++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 26 deletions(-) diff --git a/rtengine/vng4_demosaic_RT.cc b/rtengine/vng4_demosaic_RT.cc index 0e7d8e0f9..500590b04 100644 --- a/rtengine/vng4_demosaic_RT.cc +++ b/rtengine/vng4_demosaic_RT.cc @@ -210,9 +210,7 @@ void RawImageSource::vng4_demosaic (const array2D &rawData, array2D &rawData, array2D &rawData, array2D &rawData, array2D &rawData, array2D firstRow) { - interpolate_row_rb_mul_pp (rawData, red[row - 1], blue[row - 1], green[row - 2], green[row - 1], green[row], row - 1, 1.0, 1.0, 1.0, 0, W, 1); + interpolate_row_rb_mul_pp(rawData, red[row - 1], blue[row - 1], green[row - 2], green[row - 1], green[row], row - 1, 1.0, 1.0, 1.0, 0, W, 1); } if(plistenerActive) { @@ -314,22 +306,24 @@ void RawImageSource::vng4_demosaic (const array2D &rawData, array2D 2 && firstRow < H - 3) { - interpolate_row_rb_mul_pp (rawData, red[firstRow], blue[firstRow], green[firstRow - 1], green[firstRow], green[firstRow + 1], firstRow, 1.0, 1.0, 1.0, 0, W, 1); + interpolate_row_rb_mul_pp(rawData, red[firstRow], blue[firstRow], green[firstRow - 1], green[firstRow], green[firstRow + 1], firstRow, 1.0, 1.0, 1.0, 0, W, 1); } if (lastRow > 2 && lastRow < H - 3) { - interpolate_row_rb_mul_pp (rawData, red[lastRow], blue[lastRow], green[lastRow - 1], green[lastRow], green[lastRow + 1], lastRow, 1.0, 1.0, 1.0, 0, W, 1); + interpolate_row_rb_mul_pp(rawData, red[lastRow], blue[lastRow], green[lastRow - 1], green[lastRow], green[lastRow + 1], lastRow, 1.0, 1.0, 1.0, 0, W, 1); + } +#ifdef _OPENMP + #pragma omp single +#endif + { + // let the first thread, which is out of work, do the border interpolation + border_interpolate2(W, H, 3, rawData, red, green, blue); } } + free (code[0][0]); free (image); - if(plistenerActive) { - plistener->setProgress (0.98); - } - - border_interpolate2(W, H, 3, rawData, red, green, blue); - if(plistenerActive) { plistener->setProgress (1.0); } From 7fb90644d38cfe801e4ab74cee934d7229c903e8 Mon Sep 17 00:00:00 2001 From: Alberto Griggio Date: Sat, 27 Oct 2018 15:25:38 +0200 Subject: [PATCH 24/42] dehaze: tweak epsilon to avoid artifacts in corner cases --- rtengine/ipdehaze.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rtengine/ipdehaze.cc b/rtengine/ipdehaze.cc index 92eaa4062..fecc73e7d 100644 --- a/rtengine/ipdehaze.cc +++ b/rtengine/ipdehaze.cc @@ -282,7 +282,7 @@ void ImProcFunctions::dehaze(Imagefloat *img) } const int radius = patchsize * 4; - const float epsilon = 1e-7; + const float epsilon = 1e-5; array2D &t = t_tilde; { From 47cfcd51d49b9f6890558ee0d4dce3e9e69979a5 Mon Sep 17 00:00:00 2001 From: heckflosse Date: Sat, 27 Oct 2018 18:46:02 +0200 Subject: [PATCH 25/42] vng4 demosaic: removed StopWatch, fixes #4897 --- rtengine/vng4_demosaic_RT.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rtengine/vng4_demosaic_RT.cc b/rtengine/vng4_demosaic_RT.cc index 500590b04..5ed0b35c7 100644 --- a/rtengine/vng4_demosaic_RT.cc +++ b/rtengine/vng4_demosaic_RT.cc @@ -24,13 +24,13 @@ #include "rawimagesource.h" #include "rawimagesource_i.h" #include "../rtgui/multilangmgr.h" -#define BENCHMARK +//#define BENCHMARK #include "StopWatch.h" namespace rtengine { #define fc(row,col) (prefilters >> ((((row) << 1 & 14) + ((col) & 1)) << 1) & 3) -typedef unsigned short ushort; + void RawImageSource::vng4_demosaic (const array2D &rawData, array2D &red, array2D &green, array2D &blue, bool keepGreens) { BENCHFUN From 13abcd0f6c5519744cd6acb523c2a1a86bfa4847 Mon Sep 17 00:00:00 2001 From: heckflosse Date: Sun, 28 Oct 2018 20:37:34 +0100 Subject: [PATCH 26/42] vng4 demosaic: another very small speedup, #4633 --- rtengine/rawimagesource.h | 2 +- rtengine/vng4_demosaic_RT.cc | 104 +++++++++++++++-------------------- 2 files changed, 46 insertions(+), 60 deletions(-) diff --git a/rtengine/rawimagesource.h b/rtengine/rawimagesource.h index f78a4121b..8ee403ea2 100644 --- a/rtengine/rawimagesource.h +++ b/rtengine/rawimagesource.h @@ -269,7 +269,7 @@ protected: void nodemosaic(bool bw); void eahd_demosaic(); void hphd_demosaic(); - void vng4_demosaic(const array2D &rawData, array2D &red, array2D &green, array2D &blue, bool keepGreens = false); + void vng4_demosaic(const array2D &rawData, array2D &red, array2D &green, array2D &blue); void ppg_demosaic(); void jdl_interpolate_omp(); void igv_interpolate(int winw, int winh); diff --git a/rtengine/vng4_demosaic_RT.cc b/rtengine/vng4_demosaic_RT.cc index 5ed0b35c7..ed3ef8802 100644 --- a/rtengine/vng4_demosaic_RT.cc +++ b/rtengine/vng4_demosaic_RT.cc @@ -31,7 +31,7 @@ namespace rtengine { #define fc(row,col) (prefilters >> ((((row) << 1 & 14) + ((col) & 1)) << 1) & 3) -void RawImageSource::vng4_demosaic (const array2D &rawData, array2D &red, array2D &green, array2D &blue, bool keepGreens) +void RawImageSource::vng4_demosaic (const array2D &rawData, array2D &red, array2D &green, array2D &blue) { BENCHFUN const signed short int *cp, terms[] = { @@ -227,67 +227,53 @@ void RawImageSource::vng4_demosaic (const array2D &rawData, array2D firstRow) { interpolate_row_rb_mul_pp(rawData, red[row - 1], blue[row - 1], green[row - 2], green[row - 1], green[row], row - 1, 1.0, 1.0, 1.0, 0, W, 1); From 4d9871110bd47bb8399f204d6f6ba75c6267639e Mon Sep 17 00:00:00 2001 From: Alberto Griggio Date: Mon, 29 Oct 2018 09:36:17 +0100 Subject: [PATCH 27/42] improved GUI for the "image type" field of dynamic profile rules --- rtdata/languages/default | 4 +++ rtgui/dynamicprofilepanel.cc | 50 +++++++++++++++++++++++++++++++----- rtgui/dynamicprofilepanel.h | 3 +-- 3 files changed, 49 insertions(+), 8 deletions(-) diff --git a/rtdata/languages/default b/rtdata/languages/default index cc978ce92..1368b43f8 100644 --- a/rtdata/languages/default +++ b/rtdata/languages/default @@ -43,6 +43,10 @@ DYNPROFILEEDITOR_DELETE;Delete DYNPROFILEEDITOR_EDIT;Edit DYNPROFILEEDITOR_EDIT_RULE;Edit Dynamic Profile Rule DYNPROFILEEDITOR_ENTRY_TOOLTIP;The matching is case insensitive.\nUse the "re:" prefix to enter\na regular expression. +DYNPROFILEEDITOR_IMGTYPE_ANY;Any +DYNPROFILEEDITOR_IMGTYPE_STD;Standard +DYNPROFILEEDITOR_IMGTYPE_HDR;HDR +DYNPROFILEEDITOR_IMGTYPE_PS;Pixel Shift DYNPROFILEEDITOR_MOVE_DOWN;Move Down DYNPROFILEEDITOR_MOVE_UP;Move Up DYNPROFILEEDITOR_NEW;New diff --git a/rtgui/dynamicprofilepanel.cc b/rtgui/dynamicprofilepanel.cc index d7e8f356a..d83c70669 100644 --- a/rtgui/dynamicprofilepanel.cc +++ b/rtgui/dynamicprofilepanel.cc @@ -41,7 +41,17 @@ DynamicProfilePanel::EditDialog::EditDialog (const Glib::ustring &title, Gtk::Wi add_optional (M ("EXIFFILTER_CAMERA"), has_camera_, camera_); add_optional (M ("EXIFFILTER_LENS"), has_lens_, lens_); - add_optional (M ("EXIFFILTER_IMAGETYPE"), has_imagetype_, imagetype_); + + imagetype_ = Gtk::manage (new MyComboBoxText()); + imagetype_->append(Glib::ustring("(") + M("DYNPROFILEEDITOR_IMGTYPE_ANY") + ")"); + imagetype_->append(M("DYNPROFILEEDITOR_IMGTYPE_STD")); + imagetype_->append(M("DYNPROFILEEDITOR_IMGTYPE_HDR")); + imagetype_->append(M("DYNPROFILEEDITOR_IMGTYPE_PS")); + imagetype_->set_active(0); + hb = Gtk::manage (new Gtk::HBox()); + hb->pack_start (*Gtk::manage (new Gtk::Label (M ("EXIFFILTER_IMAGETYPE"))), false, false, 4); + hb->pack_start (*imagetype_, true, true, 2); + get_content_area()->pack_start (*hb, Gtk::PACK_SHRINK, 4); add_range (M ("EXIFFILTER_ISO"), iso_min_, iso_max_); add_range (M ("EXIFFILTER_APERTURE"), fnumber_min_, fnumber_max_); @@ -82,8 +92,17 @@ void DynamicProfilePanel::EditDialog::set_rule ( has_lens_->set_active (rule.lens.enabled); lens_->set_text (rule.lens.value); - has_imagetype_->set_active (rule.imagetype.enabled); - imagetype_->set_text (rule.imagetype.value); + if (!rule.imagetype.enabled) { + imagetype_->set_active(0); + } else if (rule.imagetype.value == "STD") { + imagetype_->set_active(1); + } else if (rule.imagetype.value == "HDR") { + imagetype_->set_active(2); + } else if (rule.imagetype.value == "PS") { + imagetype_->set_active(3); + } else { + imagetype_->set_active(0); + } profilepath_->updateProfileList(); @@ -116,8 +135,20 @@ DynamicProfileRule DynamicProfilePanel::EditDialog::get_rule() ret.lens.enabled = has_lens_->get_active(); ret.lens.value = lens_->get_text(); - ret.imagetype.enabled = has_imagetype_->get_active(); - ret.imagetype.value = imagetype_->get_text(); + ret.imagetype.enabled = imagetype_->get_active_row_number() > 0; + switch (imagetype_->get_active_row_number()) { + case 1: + ret.imagetype.value = "STD"; + break; + case 2: + ret.imagetype.value = "HDR"; + break; + case 3: + ret.imagetype.value = "PS"; + break; + default: + ret.imagetype.value = ""; + } ret.profilepath = profilepath_->getFullPathFromActiveRow(); @@ -478,7 +509,14 @@ void DynamicProfilePanel::render_lens ( void DynamicProfilePanel::render_imagetype ( Gtk::CellRenderer *cell, const Gtk::TreeModel::iterator &iter) { - RENDER_OPTIONAL_ (imagetype); + auto row = *iter; + Gtk::CellRendererText *ct = static_cast(cell); + DynamicProfileRule::Optional o = row[columns_.imagetype]; + if (o.enabled) { + ct->property_text() = M(std::string("DYNPROFILEEDITOR_IMGTYPE_") + o.value); + } else { \ + ct->property_text() = ""; + } } #undef RENDER_OPTIONAL_ diff --git a/rtgui/dynamicprofilepanel.h b/rtgui/dynamicprofilepanel.h index 3b5bec4df..e271edc5a 100644 --- a/rtgui/dynamicprofilepanel.h +++ b/rtgui/dynamicprofilepanel.h @@ -112,8 +112,7 @@ private: Gtk::CheckButton *has_lens_; Gtk::Entry *lens_; - Gtk::CheckButton *has_imagetype_; - Gtk::Entry *imagetype_; + MyComboBoxText *imagetype_; ProfileStoreComboBox *profilepath_; }; From 894fb8d9b3d847b9515742501af5f50e36c750a6 Mon Sep 17 00:00:00 2001 From: heckflosse Date: Tue, 30 Oct 2018 13:45:44 +0100 Subject: [PATCH 28/42] vng4 demosaic: another small speedup, #4633 --- rtengine/vng4_demosaic_RT.cc | 216 ++++++++++++++++++++++++----------- 1 file changed, 148 insertions(+), 68 deletions(-) diff --git a/rtengine/vng4_demosaic_RT.cc b/rtengine/vng4_demosaic_RT.cc index ed3ef8802..1c7f27dea 100644 --- a/rtengine/vng4_demosaic_RT.cc +++ b/rtengine/vng4_demosaic_RT.cc @@ -22,12 +22,41 @@ #include "rtengine.h" #include "rawimagesource.h" -#include "rawimagesource_i.h" #include "../rtgui/multilangmgr.h" //#define BENCHMARK #include "StopWatch.h" +namespace { + +using namespace rtengine; + +inline void vng4interpolate_row_redblue (const RawImage *ri, const array2D &rawData, float* ar, float* ab, const float * const pg, const float * const cg, const float * const ng, int i, int width) +{ + if (ri->ISBLUE(i, 0) || ri->ISBLUE(i, 1)) { + std::swap(ar, ab); + } + + // RGRGR or GRGRGR line + for (int j = 3; j < width - 3; ++j) { + if (!ri->ISGREEN(i, j)) { + // keep original value + ar[j] = rawData[i][j]; + // cross interpolation of red/blue + float rb = (rawData[i - 1][j - 1] - pg[j - 1] + rawData[i + 1][j - 1] - ng[j - 1]); + rb += (rawData[i - 1][j + 1] - pg[j + 1] + rawData[i + 1][j + 1] - ng[j + 1]); + ab[j] = cg[j] + rb * 0.25f; + } else { + // linear R/B-G interpolation horizontally + ar[j] = cg[j] + (rawData[i][j - 1] - cg[j - 1] + rawData[i][j + 1] - cg[j + 1]) / 2; + // linear B/R-G interpolation vertically + ab[j] = cg[j] + (rawData[i - 1][j] - pg[j] + rawData[i + 1][j] - ng[j]) / 2; + } + } +} +} + namespace rtengine + { #define fc(row,col) (prefilters >> ((((row) << 1 & 14) + ((col) & 1)) << 1) & 3) @@ -74,65 +103,106 @@ void RawImageSource::vng4_demosaic (const array2D &rawData, array2D firstRow) { + int row = ii - 1; + for (int col = 1; col < width - 1; col++) { + float * pix = image[row * width + col]; + int * ip = lcode[row & 15][col & 15]; + float sum[4] = {}; + + for (int i = 0; i < 8; i++, ip += 2) { + sum[ip[1]] += pix[ip[0]] * mul[row & 15][col & 15][i]; + } + + for (unsigned int i = 0; i < colors - 1; i++, ip++) { + pix[ip[0]] = sum[ip[0]] * csum[row & 15][col & 15][i]; + } + } + } + } + + // now all rows are processed except the first and last row of each chunk + // let's process them now but skip row 0 and row H - 1 + if (firstRow > 0 && firstRow < H - 1) { + const int row = firstRow; for (int col = 1; col < width - 1; col++) { float * pix = image[row * width + col]; int * ip = lcode[row & 15][col & 15]; - float sum[4]; - memset (sum, 0, sizeof sum); + float sum[4] = {}; + + for (int i = 0; i < 8; i++, ip += 2) { + sum[ip[1]] += pix[ip[0]] * mul[row & 15][col & 15][i]; + } + + for (unsigned int i = 0; i < colors - 1; i++, ip++) { + pix[ip[0]] = sum[ip[0]] * csum[row & 15][col & 15][i]; + } + } + } + + if (lastRow > 0 && lastRow < H - 1) { + const int row = lastRow; + for (int col = 1; col < width - 1; col++) { + float * pix = image[row * width + col]; + int * ip = lcode[row & 15][col & 15]; + float sum[4] = {}; for (int i = 0; i < 8; i++, ip += 2) { sum[ip[1]] += pix[ip[0]] * mul[row & 15][col & 15][i]; @@ -145,16 +215,15 @@ void RawImageSource::vng4_demosaic (const array2D &rawData, array2D &rawData, array2D(ip++) = 1 << weight; +#else *ip++ = 1 << weight; - - for (g = 0; g < 8; g++) +#endif + for (int g = 0; g < 8; g++) if (grads & (1 << g)) { *ip++ = g; } @@ -187,7 +260,8 @@ void RawImageSource::vng4_demosaic (const array2D &rawData, array2D &rawData, array2DsetProgress (progress); } @@ -211,7 +285,7 @@ void RawImageSource::vng4_demosaic (const array2D &rawData, array2D &rawData, array2D float conversions + const float diff = std::fabs(pix[ip[0]] - pix[ip[1]]) * reinterpret_cast(ip)[2]; +#else const float diff = std::fabs(pix[ip[0]] - pix[ip[1]]) * ip[2]; +#endif gval[ip[3]] += diff; ip += 5; if (UNLIKELY(ip[-1] != -1)) { @@ -246,17 +325,18 @@ void RawImageSource::vng4_demosaic (const array2D &rawData, array2D &rawData, array2D firstRow) { - interpolate_row_rb_mul_pp(rawData, red[row - 1], blue[row - 1], green[row - 2], green[row - 1], green[row], row - 1, 1.0, 1.0, 1.0, 0, W, 1); + vng4interpolate_row_redblue(ri, rawData, red[row - 1], blue[row - 1], green[row - 2], green[row - 1], green[row], row - 1, W); } if(plistenerActive) { @@ -292,11 +372,11 @@ void RawImageSource::vng4_demosaic (const array2D &rawData, array2D 2 && firstRow < H - 3) { - interpolate_row_rb_mul_pp(rawData, red[firstRow], blue[firstRow], green[firstRow - 1], green[firstRow], green[firstRow + 1], firstRow, 1.0, 1.0, 1.0, 0, W, 1); + vng4interpolate_row_redblue(ri, rawData, red[firstRow], blue[firstRow], green[firstRow - 1], green[firstRow], green[firstRow + 1], firstRow, W); } if (lastRow > 2 && lastRow < H - 3) { - interpolate_row_rb_mul_pp(rawData, red[lastRow], blue[lastRow], green[lastRow - 1], green[lastRow], green[lastRow + 1], lastRow, 1.0, 1.0, 1.0, 0, W, 1); + vng4interpolate_row_redblue(ri, rawData, red[lastRow], blue[lastRow], green[lastRow - 1], green[lastRow], green[lastRow + 1], lastRow, W); } #ifdef _OPENMP #pragma omp single From 1dcf92322dd995f241414b11192b44140c6368b3 Mon Sep 17 00:00:00 2001 From: heckflosse Date: Tue, 30 Oct 2018 19:36:37 +0100 Subject: [PATCH 29/42] RT crashes with wrong value in profile (curves), fixes #4398 --- rtengine/curves.cc | 36 ++++++++++++++++++++++++++++ rtengine/curves.h | 8 ++++++- rtengine/procparams.cc | 9 +------ rtgui/diagonalcurveeditorsubgroup.cc | 4 ++++ rtgui/flatcurveeditorsubgroup.cc | 4 ++++ 5 files changed, 52 insertions(+), 9 deletions(-) diff --git a/rtengine/curves.cc b/rtengine/curves.cc index aab74a7de..9e3c6527e 100644 --- a/rtengine/curves.cc +++ b/rtengine/curves.cc @@ -45,6 +45,42 @@ using namespace std; namespace rtengine { +bool sanitizeCurve(std::vector& curve) +{ + // A curve is valid under one of the following conditions: + // 1) Curve has exactly one entry which is D(F)CT_Linear + // 2) Number of curve entries is > 3 and odd + // 3) curve[0] == DCT_Parametric and curve size is >= 8 and curve[1] .. curve[3] are ordered ascending and are distinct + if (curve.empty()) { + curve.push_back (DCT_Linear); + return true; + } else if(curve.size() == 1 && curve[0] != DCT_Linear) { + curve[0] = DCT_Linear; + return true; + } else if((curve.size() % 2 == 0 || curve.size() < 5) && curve[0] != DCT_Parametric) { + curve.clear(); + curve.push_back (DCT_Linear); + return true; + } else if(curve[0] == DCT_Parametric) { + if (curve.size() < 8) { + curve.clear(); + curve.push_back (DCT_Linear); + return true; + } else { + // curve[1] to curve[3] must be ordered ascending and distinct + for (int i = 1; i < 3; i++) { + if (curve[i] >= curve[i + 1]) { + curve[1] = 0.25f; + curve[2] = 0.5f; + curve[3] = 0.75f; + break; + } + } + } + } + return false; +} + Curve::Curve () : N(0), ppn(0), x(nullptr), y(nullptr), mc(0.0), mfc(0.0), msc(0.0), mhc(0.0), hashSize(1000 /* has to be initialized to the maximum value */), ypp(nullptr), x1(0.0), y1(0.0), x2(0.0), y2(0.0), x3(0.0), y3(0.0), firstPointIncluded(false), increment(0.0), nbr_points(0) {} void Curve::AddPolygons () diff --git a/rtengine/curves.h b/rtengine/curves.h index a9f4b4ace..30fb01102 100644 --- a/rtengine/curves.h +++ b/rtengine/curves.h @@ -19,9 +19,12 @@ #ifndef __CURVES_H__ #define __CURVES_H__ -#include #include #include +#include + +#include + #include "rt_math.h" #include "../rtgui/mycurve.h" #include "../rtgui/myflatcurve.h" @@ -42,6 +45,7 @@ using namespace std; namespace rtengine { + class ToneCurve; class ColorAppearance; @@ -55,6 +59,8 @@ void setUnlessOOG(T &r, T &g, T &b, const T &rr, const T &gg, const T &bb) } } +bool sanitizeCurve(std::vector& curve); + namespace curves { inline void setLutVal(const LUTf &lut, float &val) diff --git a/rtengine/procparams.cc b/rtengine/procparams.cc index 526a36765..b07778c55 100644 --- a/rtengine/procparams.cc +++ b/rtengine/procparams.cc @@ -87,13 +87,6 @@ Glib::ustring relativePathIfInside(const Glib::ustring &procparams_fname, bool f return prefix + embedded_fname.substr(dir1.length()); } -void avoidEmptyCurve(std::vector &curve) -{ - if (curve.empty()) { - curve.push_back(FCT_Linear); - } -} - void getFromKeyfile( const Glib::KeyFile& keyfile, const Glib::ustring& group_name, @@ -142,7 +135,7 @@ void getFromKeyfile( ) { value = keyfile.get_double_list(group_name, key); - avoidEmptyCurve(value); + rtengine::sanitizeCurve(value); } template diff --git a/rtgui/diagonalcurveeditorsubgroup.cc b/rtgui/diagonalcurveeditorsubgroup.cc index a022c8650..c23b25f9a 100644 --- a/rtgui/diagonalcurveeditorsubgroup.cc +++ b/rtgui/diagonalcurveeditorsubgroup.cc @@ -32,6 +32,8 @@ #include "diagonalcurveeditorsubgroup.h" #include "rtimage.h" +#include "../rtengine/curves.h" + DiagonalCurveEditorSubGroup::DiagonalCurveEditorSubGroup (CurveEditorGroup* prt, Glib::ustring& curveDir) : CurveEditorSubGroup(curveDir) { @@ -814,6 +816,8 @@ void DiagonalCurveEditorSubGroup::loadPressed () } } + rtengine::sanitizeCurve(p); + if (p[0] == (double)(DCT_Spline)) { customCurve->setPoints (p); customCurve->queue_draw (); diff --git a/rtgui/flatcurveeditorsubgroup.cc b/rtgui/flatcurveeditorsubgroup.cc index 2cc96a184..27b7ac940 100644 --- a/rtgui/flatcurveeditorsubgroup.cc +++ b/rtgui/flatcurveeditorsubgroup.cc @@ -33,6 +33,8 @@ #include "flatcurveeditorsubgroup.h" #include "rtimage.h" +#include "../rtengine/curves.h" + FlatCurveEditorSubGroup::FlatCurveEditorSubGroup (CurveEditorGroup* prt, Glib::ustring& curveDir) : CurveEditorSubGroup(curveDir) { @@ -418,6 +420,8 @@ void FlatCurveEditorSubGroup::loadPressed () } } + rtengine::sanitizeCurve(p); + if (p[0] == (double)(FCT_MinMaxCPoints)) { CPointsCurve->setPoints (p); CPointsCurve->queue_draw (); From cef5d12779859965a5f7bddfe9118333f28b95cb Mon Sep 17 00:00:00 2001 From: Morgan Hardwood Date: Tue, 30 Oct 2018 21:18:21 +0100 Subject: [PATCH 30/42] AllowUpscaling=false for old PP3s PP3s from before the Allow Upscaling option's introduction to the Resize tool should defaut to not allow upscaling. Closes #4643 --- rtengine/procparams.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rtengine/procparams.cc b/rtengine/procparams.cc index b07778c55..f5e598b75 100644 --- a/rtengine/procparams.cc +++ b/rtengine/procparams.cc @@ -4207,7 +4207,7 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited) if (ppVersion >= 339) { assignFromKeyfile(keyFile, "Resize", "AllowUpscaling", pedited, resize.allowUpscaling, pedited->resize.allowUpscaling); } else { - resize.allowUpscaling = true; + resize.allowUpscaling = false; if (pedited) { pedited->resize.allowUpscaling = true; } From 43876abb81471cabbd6219ce6188c68056fc35b2 Mon Sep 17 00:00:00 2001 From: Morgan Hardwood Date: Tue, 30 Oct 2018 23:56:49 +0100 Subject: [PATCH 31/42] Reverted changes to 'default' language file #4898 Commit 14ac4b accidentally wiped all non-ASCII characters from the file while adding new keys. This commit restores them. --- rtdata/languages/default | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/rtdata/languages/default b/rtdata/languages/default index d9cc7f4a2..370d8645d 100644 --- a/rtdata/languages/default +++ b/rtdata/languages/default @@ -398,7 +398,7 @@ HISTORY_MSG_145;Microcontrast - Uniformity HISTORY_MSG_146;Edge sharpening HISTORY_MSG_147;ES - Luminance only HISTORY_MSG_148;Microcontrast -HISTORY_MSG_149;Microcontrast - 33 matrix +HISTORY_MSG_149;Microcontrast - 3×3 matrix HISTORY_MSG_150;Post-demosaic artifact/noise red. HISTORY_MSG_151;Vibrance HISTORY_MSG_152;Vib - Pastel tones @@ -812,7 +812,7 @@ IPTCPANEL_CITY;City IPTCPANEL_CITYHINT;Enter the name of the city pictured in this image. IPTCPANEL_COPYHINT;Copy IPTC settings to clipboard. IPTCPANEL_COPYRIGHT;Copyright notice -IPTCPANEL_COPYRIGHTHINT;Enter a Notice on the current owner of the Copyright for this image, such as 2008 Jane Doe. +IPTCPANEL_COPYRIGHTHINT;Enter a Notice on the current owner of the Copyright for this image, such as ©2008 Jane Doe. IPTCPANEL_COUNTRY;Country IPTCPANEL_COUNTRYHINT;Enter the name of the country pictured in this image. IPTCPANEL_CREATOR;Creator @@ -1372,9 +1372,9 @@ TP_COARSETRAF_TOOLTIP_ROTLEFT;Rotate left.\n\nShortcuts:\n[ - Multiple Ed TP_COARSETRAF_TOOLTIP_ROTRIGHT;Rotate right.\n\nShortcuts:\n] - Multiple Editor Tabs Mode,\nAlt-] - Single Editor Tab Mode. TP_COARSETRAF_TOOLTIP_VFLIP;Flip vertically. TP_COLORAPP_ADAPTSCENE;Scene absolute luminance -TP_COLORAPP_ADAPTSCENE_TOOLTIP;Absolute luminance of the scene environment (cd/m).\n1) Calculated from the Exif data:\nShutter speed - ISO speed - F number - camera exposure correction.\n2) Calculated from the raw white point and RT's Exposure Compensation slider. -TP_COLORAPP_ADAPTVIEWING;Viewing absolute luminance (cd/m) -TP_COLORAPP_ADAPTVIEWING_TOOLTIP;Absolute luminance of the viewing environment\n(usually 16cd/m). +TP_COLORAPP_ADAPTSCENE_TOOLTIP;Absolute luminance of the scene environment (cd/m²).\n1) Calculated from the Exif data:\nShutter speed - ISO speed - F number - camera exposure correction.\n2) Calculated from the raw white point and RT's Exposure Compensation slider. +TP_COLORAPP_ADAPTVIEWING;Viewing absolute luminance (cd/m²) +TP_COLORAPP_ADAPTVIEWING_TOOLTIP;Absolute luminance of the viewing environment\n(usually 16cd/m²). TP_COLORAPP_ADAP_AUTO_TOOLTIP;If the checkbox is checked (recommended) RawTherapee calculates an optimum value from the Exif data.\nTo set the value manually, uncheck the checkbox first. TP_COLORAPP_ALGO;Algorithm TP_COLORAPP_ALGO_ALL;All @@ -1411,7 +1411,7 @@ TP_COLORAPP_FREE;Free temp+green + CAT02 + [output] TP_COLORAPP_GAMUT;Gamut control (L*a*b*) TP_COLORAPP_GAMUT_TOOLTIP;Allow gamut control in L*a*b* mode. TP_COLORAPP_HUE;Hue (h) -TP_COLORAPP_HUE_TOOLTIP;Hue (h) - angle between 0 and 360. +TP_COLORAPP_HUE_TOOLTIP;Hue (h) - angle between 0° and 360°. TP_COLORAPP_LABEL;CIE Color Appearance Model 2002 TP_COLORAPP_LABEL_CAM02;Image Adjustments TP_COLORAPP_LABEL_SCENE;Scene Conditions @@ -1562,16 +1562,16 @@ TP_DIRPYRDENOISE_MEDIAN_METHOD_RGB;RGB TP_DIRPYRDENOISE_MEDIAN_METHOD_TOOLTIP;When using the "Luminance only" and "L*a*b*" methods, median filtering will be performed just after the wavelet step in the noise reduction pipeline.\nWhen using the "RGB" mode, it will be performed at the very end of the noise reduction pipeline. TP_DIRPYRDENOISE_MEDIAN_METHOD_WEIGHTED;Weighted L* (little) + a*b* (normal) TP_DIRPYRDENOISE_MEDIAN_PASSES;Median iterations -TP_DIRPYRDENOISE_MEDIAN_PASSES_TOOLTIP;Applying three median filter iterations with a 33 window size often leads to better results than using one median filter iteration with a 77 window size. +TP_DIRPYRDENOISE_MEDIAN_PASSES_TOOLTIP;Applying three median filter iterations with a 3×3 window size often leads to better results than using one median filter iteration with a 7×7 window size. TP_DIRPYRDENOISE_MEDIAN_TYPE;Median type -TP_DIRPYRDENOISE_MEDIAN_TYPE_TOOLTIP;Apply a median filter of the desired window size. The larger the window's size, the longer it takes.\n\n33 soft: treats 5 pixels in a 33 pixel window.\n33: treats 9 pixels in a 33 pixel window.\n55 soft: treats 13 pixels in a 55 pixel window.\n55: treats 25 pixels in a 55 pixel window.\n77: treats 49 pixels in a 77 pixel window.\n99: treats 81 pixels in a 99 pixel window.\n\nSometimes it is possible to achieve higher quality running several iterations with a smaller window size than one iteration with a larger one. +TP_DIRPYRDENOISE_MEDIAN_TYPE_TOOLTIP;Apply a median filter of the desired window size. The larger the window's size, the longer it takes.\n\n3×3 soft: treats 5 pixels in a 3×3 pixel window.\n3×3: treats 9 pixels in a 3×3 pixel window.\n5×5 soft: treats 13 pixels in a 5×5 pixel window.\n5×5: treats 25 pixels in a 5×5 pixel window.\n7×7: treats 49 pixels in a 7×7 pixel window.\n9×9: treats 81 pixels in a 9×9 pixel window.\n\nSometimes it is possible to achieve higher quality running several iterations with a smaller window size than one iteration with a larger one. TP_DIRPYRDENOISE_SLI;Slider -TP_DIRPYRDENOISE_TYPE_3X3;33 -TP_DIRPYRDENOISE_TYPE_3X3SOFT;33 soft -TP_DIRPYRDENOISE_TYPE_5X5;55 -TP_DIRPYRDENOISE_TYPE_5X5SOFT;55 soft -TP_DIRPYRDENOISE_TYPE_7X7;77 -TP_DIRPYRDENOISE_TYPE_9X9;99 +TP_DIRPYRDENOISE_TYPE_3X3;3×3 +TP_DIRPYRDENOISE_TYPE_3X3SOFT;3×3 soft +TP_DIRPYRDENOISE_TYPE_5X5;5×5 +TP_DIRPYRDENOISE_TYPE_5X5SOFT;5×5 soft +TP_DIRPYRDENOISE_TYPE_7X7;7×7 +TP_DIRPYRDENOISE_TYPE_9X9;9×9 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_ARTIF;Reduce artifacts @@ -2017,7 +2017,7 @@ TP_SHARPENING_USM;Unsharp Mask TP_SHARPENMICRO_AMOUNT;Quantity TP_SHARPENMICRO_CONTRAST;Contrast threshold TP_SHARPENMICRO_LABEL;Microcontrast -TP_SHARPENMICRO_MATRIX;33 matrix instead of 55 +TP_SHARPENMICRO_MATRIX;3×3 matrix instead of 5×5 TP_SHARPENMICRO_UNIFORMITY;Uniformity TP_SOFTLIGHT_LABEL;Soft Light TP_SOFTLIGHT_STRENGTH;Strength From f6c864d477192a16535b27de21a006024734ff78 Mon Sep 17 00:00:00 2001 From: heckflosse Date: Wed, 31 Oct 2018 15:02:53 +0100 Subject: [PATCH 32/42] Get rid of aehistogram files in RT cache, fixes #4904 --- rtengine/rtthumbnail.cc | 69 +++++++++++++++++++++++++++++++++++++++-- rtengine/rtthumbnail.h | 8 +++++ rtgui/thumbnail.cc | 13 +++++--- 3 files changed, 82 insertions(+), 8 deletions(-) diff --git a/rtengine/rtthumbnail.cc b/rtengine/rtthumbnail.cc index afd8836a1..1210518d4 100644 --- a/rtengine/rtthumbnail.cc +++ b/rtengine/rtthumbnail.cc @@ -279,6 +279,11 @@ Thumbnail* Thumbnail::loadFromImage (const Glib::ustring& fname, int &w, int &h, printf ("loadFromImage: Unsupported image type \"%s\"!\n", img->getType()); } + ProcParams paramsForAutoExp; // Dummy for constructor + ImProcFunctions ipf (¶msForAutoExp, false); + ipf.getAutoExp (tpp->aeHistogram, tpp->aeHistCompression, 0.02, tpp->aeExposureCompensation, tpp->aeLightness, tpp->aeContrast, tpp->aeBlack, tpp->aeHighlightCompression, tpp->aeHighlightCompressionThreshold); + tpp->aeValid = true; + if (n > 0) { ColorTemp cTemp; @@ -923,6 +928,11 @@ Thumbnail* Thumbnail::loadFromRaw (const Glib::ustring& fname, RawMetaDataLocati } } } + ProcParams paramsForAutoExp; // Dummy for constructor + ImProcFunctions ipf (¶msForAutoExp, false); + ipf.getAutoExp (tpp->aeHistogram, tpp->aeHistCompression, 0.02, tpp->aeExposureCompensation, tpp->aeLightness, tpp->aeContrast, tpp->aeBlack, tpp->aeHighlightCompression, tpp->aeHighlightCompressionThreshold); + tpp->aeValid = true; + if (ri->get_colors() == 1) { pixSum[0] = pixSum[1] = pixSum[2] = 1.; n[0] = n[1] = n[2] = 1; @@ -993,6 +1003,13 @@ Thumbnail::Thumbnail () : wbEqual (-1.0), wbTempBias (0.0), aeHistCompression (3), + aeValid(false), + aeExposureCompensation(0.0), + aeLightness(0), + aeContrast(0), + aeBlack(0), + aeHighlightCompression(0), + aeHighlightCompressionThreshold(0), embProfileLength (0), embProfileData (nullptr), embProfile (nullptr), @@ -1224,8 +1241,17 @@ IImage8* Thumbnail::processImage (const procparams::ProcParams& params, eSensorT int hlcompr = params.toneCurve.hlcompr; int hlcomprthresh = params.toneCurve.hlcomprthresh; - if (params.toneCurve.autoexp && aeHistogram) { - ipf.getAutoExp (aeHistogram, aeHistCompression, params.toneCurve.clip, expcomp, bright, contr, black, hlcompr, hlcomprthresh); + if (params.toneCurve.autoexp) { + if (aeValid) { + expcomp = aeExposureCompensation; + bright = aeLightness; + contr = aeContrast; + black = aeBlack; + hlcompr = aeHighlightCompression; + hlcomprthresh = aeHighlightCompressionThreshold; + } else if (aeHistogram) { + ipf.getAutoExp (aeHistogram, aeHistCompression, 0.02, expcomp, bright, contr, black, hlcompr, hlcomprthresh); + } } LUTf curve1 (65536); @@ -1992,6 +2018,38 @@ bool Thumbnail::readData (const Glib::ustring& fname) aeHistCompression = keyFile.get_integer ("LiveThumbData", "AEHistCompression"); } + aeValid = true; + if (keyFile.has_key ("LiveThumbData", "AEExposureCompensation")) { + aeExposureCompensation = keyFile.get_double ("LiveThumbData", "AEExposureCompensation"); + } else { + aeValid = false; + } + if (keyFile.has_key ("LiveThumbData", "AELightness")) { + aeLightness = keyFile.get_integer ("LiveThumbData", "AELightness"); + } else { + aeValid = false; + } + if (keyFile.has_key ("LiveThumbData", "AEContrast")) { + aeContrast = keyFile.get_integer ("LiveThumbData", "AEContrast"); + } else { + aeValid = false; + } + if (keyFile.has_key ("LiveThumbData", "AEBlack")) { + aeBlack = keyFile.get_integer ("LiveThumbData", "AEBlack"); + } else { + aeValid = false; + } + if (keyFile.has_key ("LiveThumbData", "AEHighlightCompression")) { + aeHighlightCompression = keyFile.get_integer ("LiveThumbData", "AEHighlightCompression"); + } else { + aeValid = false; + } + if (keyFile.has_key ("LiveThumbData", "AEHighlightCompressionThreshold")) { + aeHighlightCompressionThreshold = keyFile.get_integer ("LiveThumbData", "AEHighlightCompressionThreshold"); + } else { + aeValid = false; + } + if (keyFile.has_key ("LiveThumbData", "RedMultiplier")) { redMultiplier = keyFile.get_double ("LiveThumbData", "RedMultiplier"); } @@ -2065,7 +2123,12 @@ bool Thumbnail::writeData (const Glib::ustring& fname) keyFile.set_double ("LiveThumbData", "RedAWBMul", redAWBMul); keyFile.set_double ("LiveThumbData", "GreenAWBMul", greenAWBMul); keyFile.set_double ("LiveThumbData", "BlueAWBMul", blueAWBMul); - keyFile.set_integer ("LiveThumbData", "AEHistCompression", aeHistCompression); + keyFile.set_double ("LiveThumbData", "AEExposureCompensation", aeExposureCompensation); + keyFile.set_integer ("LiveThumbData", "AELightness", aeLightness); + keyFile.set_integer ("LiveThumbData", "AEContrast", aeContrast); + keyFile.set_integer ("LiveThumbData", "AEBlack", aeBlack); + keyFile.set_integer ("LiveThumbData", "AEHighlightCompression", aeHighlightCompression); + keyFile.set_integer ("LiveThumbData", "AEHighlightCompressionThreshold", aeHighlightCompressionThreshold); keyFile.set_double ("LiveThumbData", "RedMultiplier", redMultiplier); keyFile.set_double ("LiveThumbData", "GreenMultiplier", greenMultiplier); keyFile.set_double ("LiveThumbData", "BlueMultiplier", blueMultiplier); diff --git a/rtengine/rtthumbnail.h b/rtengine/rtthumbnail.h index 558d136ee..667d8e1c9 100644 --- a/rtengine/rtthumbnail.h +++ b/rtengine/rtthumbnail.h @@ -50,6 +50,13 @@ class Thumbnail double autoWBTemp, autoWBGreen, wbEqual, wbTempBias; // autoWBTemp and autoWBGreen are updated each time autoWB is requested and if wbEqual has been modified LUTu aeHistogram; int aeHistCompression; + bool aeValid; + double aeExposureCompensation; + int aeLightness; + int aeContrast; + int aeBlack; + int aeHighlightCompression; + int aeHighlightCompressionThreshold; int embProfileLength; unsigned char* embProfileData; cmsHPROFILE embProfile; @@ -100,6 +107,7 @@ public: bool readAEHistogram (const Glib::ustring& fname); bool writeAEHistogram (const Glib::ustring& fname); + bool isAeValid() { return aeValid; }; unsigned char* getImage8Data(); // accessor to the 8bit image if it is one, which should be the case for the "Inspector" mode. // Hombre: ... let's hope that proper template can make this cleaner diff --git a/rtgui/thumbnail.cc b/rtgui/thumbnail.cc index c2d23eab2..4921a2d56 100644 --- a/rtgui/thumbnail.cc +++ b/rtgui/thumbnail.cc @@ -854,8 +854,10 @@ void Thumbnail::_loadThumbnail(bool firstTrial) } if ( cfs.thumbImgType == CacheImageData::FULL_THUMBNAIL ) { - // load aehistogram - tpp->readAEHistogram (getCacheFileName ("aehistograms", "")); + if(!tpp->isAeValid()) { + // load aehistogram + tpp->readAEHistogram (getCacheFileName ("aehistograms", "")); + } // load embedded profile tpp->readEmbProfile (getCacheFileName ("embprofiles", ".icc")); @@ -907,9 +909,10 @@ void Thumbnail::_saveThumbnail () // save thumbnail image tpp->writeImage (getCacheFileName ("images", "")); - // save aehistogram - tpp->writeAEHistogram (getCacheFileName ("aehistograms", "")); - + if(!tpp->isAeValid()) { + // save aehistogram + tpp->writeAEHistogram (getCacheFileName ("aehistograms", "")); + } // save embedded profile tpp->writeEmbProfile (getCacheFileName ("embprofiles", ".icc")); From 310e7343918d9c34ab7fc2ffd3ef8a670b22dca7 Mon Sep 17 00:00:00 2001 From: heckflosse Date: Wed, 31 Oct 2018 16:21:26 +0100 Subject: [PATCH 33/42] Don't create aehistograms folder in RT cache, #4904 --- rtgui/cachemanager.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/rtgui/cachemanager.cc b/rtgui/cachemanager.cc index 5b18d5d33..c1f81a0d2 100644 --- a/rtgui/cachemanager.cc +++ b/rtgui/cachemanager.cc @@ -57,7 +57,9 @@ void CacheManager::init () auto error = g_mkdir_with_parents (baseDir.c_str(), cacheDirMode); for (const auto& cacheDir : cacheDirs) { - error |= g_mkdir_with_parents (Glib::build_filename (baseDir, cacheDir).c_str(), cacheDirMode); + if (strncmp(cacheDir, "aehistograms", 12)) { // don't create aehistograms folder. + error |= g_mkdir_with_parents (Glib::build_filename (baseDir, cacheDir).c_str(), cacheDirMode); + } } if (error != 0 && options.rtSettings.verbose) { From 473e4bc2369bfa9c7928b9afa1fb9c168b233e58 Mon Sep 17 00:00:00 2001 From: heckflosse Date: Wed, 31 Oct 2018 17:22:03 +0100 Subject: [PATCH 34/42] clear cache data folder, #4904 --- rtgui/cachemanager.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/rtgui/cachemanager.cc b/rtgui/cachemanager.cc index c1f81a0d2..06f4ad237 100644 --- a/rtgui/cachemanager.cc +++ b/rtgui/cachemanager.cc @@ -240,6 +240,7 @@ void CacheManager::clearImages () const { MyMutex::MyLock lock (mutex); + deleteDir ("data"); deleteDir ("images"); deleteDir ("aehistograms"); deleteDir ("embprofiles"); From fb97eeaa5abc5c52767ec0ad7870de816df3c97f Mon Sep 17 00:00:00 2001 From: Alberto Griggio Date: Wed, 31 Oct 2018 17:53:47 +0100 Subject: [PATCH 35/42] guided filter: fixed bug due to overlapping input and output arrays --- rtengine/guidedfilter.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rtengine/guidedfilter.cc b/rtengine/guidedfilter.cc index 4e31fa300..790245b20 100644 --- a/rtengine/guidedfilter.cc +++ b/rtengine/guidedfilter.cc @@ -215,7 +215,7 @@ void guidedFilter(const array2D &guide, const array2D &src, array2 f_upsample(meanA, meana); DEBUG_DUMP(meanA); - array2D &meanB = q; + array2D meanB(W, H); f_upsample(meanB, meanb); DEBUG_DUMP(meanB); From bfe2ce7fe1f43616b0dc0dca06c340d7349cac78 Mon Sep 17 00:00:00 2001 From: heckflosse Date: Wed, 31 Oct 2018 20:52:16 +0100 Subject: [PATCH 36/42] Don't check for .jpg, .cust, .cust16 files in cache/images folder, #4904 --- rtgui/cachemanager.cc | 6 ------ rtgui/thumbnail.cc | 7 +------ 2 files changed, 1 insertion(+), 12 deletions(-) diff --git a/rtgui/cachemanager.cc b/rtgui/cachemanager.cc index 06f4ad237..919f76f6d 100644 --- a/rtgui/cachemanager.cc +++ b/rtgui/cachemanager.cc @@ -185,9 +185,6 @@ void CacheManager::renameEntry (const std::string& oldfilename, const std::strin auto error = g_rename (getCacheFileName ("profiles", oldfilename, paramFileExtension, oldmd5).c_str (), getCacheFileName ("profiles", newfilename, paramFileExtension, newmd5).c_str ()); error |= g_rename (getCacheFileName ("images", oldfilename, ".rtti", oldmd5).c_str (), getCacheFileName ("images", newfilename, ".rtti", newmd5).c_str ()); - error |= g_rename (getCacheFileName ("images", oldfilename, ".cust16", oldmd5).c_str (), getCacheFileName ("images", newfilename, ".cust16", newmd5).c_str ()); - error |= g_rename (getCacheFileName ("images", oldfilename, ".cust", oldmd5).c_str (), getCacheFileName ("images", newfilename, ".cust", newmd5).c_str ()); - error |= g_rename (getCacheFileName ("images", oldfilename, ".jpg", oldmd5).c_str (), getCacheFileName ("images", newfilename, ".jpg", newmd5).c_str ()); error |= g_rename (getCacheFileName ("aehistograms", oldfilename, "", oldmd5).c_str (), getCacheFileName ("aehistograms", newfilename, "", newmd5).c_str ()); error |= g_rename (getCacheFileName ("embprofiles", oldfilename, ".icc", oldmd5).c_str (), getCacheFileName ("embprofiles", newfilename, ".icc", newmd5).c_str ()); error |= g_rename (getCacheFileName ("data", oldfilename, ".txt", oldmd5).c_str (), getCacheFileName ("data", newfilename, ".txt", newmd5).c_str ()); @@ -278,9 +275,6 @@ void CacheManager::deleteFiles (const Glib::ustring& fname, const std::string& m } auto error = g_remove (getCacheFileName ("images", fname, ".rtti", md5).c_str ()); - error |= g_remove (getCacheFileName ("images", fname, ".cust16", md5).c_str ()); - error |= g_remove (getCacheFileName ("images", fname, ".cust", md5).c_str ()); - error |= g_remove (getCacheFileName ("images", fname, ".jpg", md5).c_str ()); error |= g_remove (getCacheFileName ("aehistograms", fname, "", md5).c_str ()); error |= g_remove (getCacheFileName ("embprofiles", fname, ".icc", md5).c_str ()); diff --git a/rtgui/thumbnail.cc b/rtgui/thumbnail.cc index 4921a2d56..d3bf4ca05 100644 --- a/rtgui/thumbnail.cc +++ b/rtgui/thumbnail.cc @@ -899,12 +899,7 @@ void Thumbnail::_saveThumbnail () return; } - if (g_remove (getCacheFileName ("images", ".rtti").c_str ()) != 0) { - // No file deleted, so we try to deleted obsolete files, if any - g_remove (getCacheFileName ("images", ".cust").c_str ()); - g_remove (getCacheFileName ("images", ".cust16").c_str ()); - g_remove (getCacheFileName ("images", ".jpg").c_str ()); - } + g_remove (getCacheFileName ("images", ".rtti").c_str ()) != 0); // save thumbnail image tpp->writeImage (getCacheFileName ("images", "")); From ea5a81b9a16eadf705b6de78dec1350849606b0c Mon Sep 17 00:00:00 2001 From: heckflosse Date: Wed, 31 Oct 2018 20:52:58 +0100 Subject: [PATCH 37/42] Don't check for .jpg, .cust, .cust16 files in cache/images folder, second try, #4904 --- rtgui/thumbnail.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rtgui/thumbnail.cc b/rtgui/thumbnail.cc index d3bf4ca05..1365117d7 100644 --- a/rtgui/thumbnail.cc +++ b/rtgui/thumbnail.cc @@ -899,7 +899,7 @@ void Thumbnail::_saveThumbnail () return; } - g_remove (getCacheFileName ("images", ".rtti").c_str ()) != 0); + g_remove (getCacheFileName ("images", ".rtti").c_str ())); // save thumbnail image tpp->writeImage (getCacheFileName ("images", "")); From ebcd737bf857a9d430ea71029770c577470aa44f Mon Sep 17 00:00:00 2001 From: heckflosse Date: Wed, 31 Oct 2018 20:57:21 +0100 Subject: [PATCH 38/42] Don't check for .jpg, .cust, .cust16 files in cache/images folder, third try, #4904 --- rtgui/thumbnail.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rtgui/thumbnail.cc b/rtgui/thumbnail.cc index 1365117d7..0ae78dd62 100644 --- a/rtgui/thumbnail.cc +++ b/rtgui/thumbnail.cc @@ -899,7 +899,7 @@ void Thumbnail::_saveThumbnail () return; } - g_remove (getCacheFileName ("images", ".rtti").c_str ())); + g_remove (getCacheFileName ("images", ".rtti").c_str ()); // save thumbnail image tpp->writeImage (getCacheFileName ("images", "")); From d65767a022704d87b654029474210ce553715259 Mon Sep 17 00:00:00 2001 From: heckflosse Date: Wed, 31 Oct 2018 22:21:43 +0100 Subject: [PATCH 39/42] Delete cache file from cache/data when using delete from cache full, #4904 --- rtgui/cachemanager.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rtgui/cachemanager.cc b/rtgui/cachemanager.cc index 919f76f6d..5f73e9e0f 100644 --- a/rtgui/cachemanager.cc +++ b/rtgui/cachemanager.cc @@ -174,7 +174,7 @@ void CacheManager::deleteEntry (const Glib::ustring& fname) void CacheManager::clearFromCache (const Glib::ustring& fname, bool purge) const { - deleteFiles (fname, getMD5 (fname), purge, purge); + deleteFiles (fname, getMD5 (fname), true, purge); } void CacheManager::renameEntry (const std::string& oldfilename, const std::string& oldmd5, const std::string& newfilename) From f89755862157db062ddc4c9fb4d0119f1f977486 Mon Sep 17 00:00:00 2001 From: Morgan Hardwood Date: Wed, 31 Oct 2018 22:34:28 +0100 Subject: [PATCH 40/42] Renamed cache context menu strings #4907 --- rtdata/languages/Catala | 2 -- rtdata/languages/Chinese (Simplified) | 2 -- rtdata/languages/Chinese (Traditional) | 2 -- rtdata/languages/Czech | 2 -- rtdata/languages/Dansk | 2 -- rtdata/languages/Deutsch | 2 -- rtdata/languages/English (UK) | 2 -- rtdata/languages/English (US) | 2 -- rtdata/languages/Espanol | 2 -- rtdata/languages/Euskara | 2 -- rtdata/languages/Francais | 2 -- rtdata/languages/Greek | 2 -- rtdata/languages/Hebrew | 2 -- rtdata/languages/Italiano | 2 -- rtdata/languages/Japanese | 2 -- rtdata/languages/Latvian | 2 -- rtdata/languages/Magyar | 2 -- rtdata/languages/Nederlands | 2 -- rtdata/languages/Norsk BM | 2 -- rtdata/languages/Polish | 2 -- rtdata/languages/Polish (Latin Characters) | 2 -- rtdata/languages/Portugues (Brasil) | 2 -- rtdata/languages/Russian | 2 -- rtdata/languages/Serbian (Cyrilic Characters) | 2 -- rtdata/languages/Serbian (Latin Characters) | 2 -- rtdata/languages/Slovak | 2 -- rtdata/languages/Suomi | 2 -- rtdata/languages/Swedish | 2 -- rtdata/languages/Turkish | 2 -- rtdata/languages/default | 4 ++-- 30 files changed, 2 insertions(+), 60 deletions(-) diff --git a/rtdata/languages/Catala b/rtdata/languages/Catala index c3a7ea1d0..1c89d23c5 100644 --- a/rtdata/languages/Catala +++ b/rtdata/languages/Catala @@ -84,8 +84,6 @@ FILEBROWSER_AUTOFLATFIELD;Auto camp pla FILEBROWSER_BROWSEPATHBUTTONHINT;Clic per navegar al path escollit FILEBROWSER_BROWSEPATHHINT;Escriviu path on buscar.\nCtrl-O dirigir-se al path de la finestra de text.\nEnter / Ctrl-Enter (en el gestor de fitxers) per a navegar allí;\n\nPath dreceres:\n ~ - directori home de l'usuari\n ! - directori de fotografies de l'usuari FILEBROWSER_CACHE;Cau -FILEBROWSER_CACHECLEARFROMFULL;Esborra el cau - tot -FILEBROWSER_CACHECLEARFROMPARTIAL;Esborra el cau - part FILEBROWSER_CLEARPROFILE;Neteja FILEBROWSER_COPYPROFILE;Copia FILEBROWSER_CURRENT_NAME;Nom actual: diff --git a/rtdata/languages/Chinese (Simplified) b/rtdata/languages/Chinese (Simplified) index 077da51c0..05b11dd4f 100644 --- a/rtdata/languages/Chinese (Simplified) +++ b/rtdata/languages/Chinese (Simplified) @@ -95,8 +95,6 @@ FILEBROWSER_AUTODARKFRAME;自动暗场 FILEBROWSER_AUTOFLATFIELD;自动平场 FILEBROWSER_BROWSEPATHBUTTONHINT;点击浏览选择的路径 FILEBROWSER_CACHE;缓存 -FILEBROWSER_CACHECLEARFROMFULL;清空缓存 -FILEBROWSER_CACHECLEARFROMPARTIAL;清理缓存 FILEBROWSER_CLEARPROFILE;清空配置 FILEBROWSER_COPYPROFILE;复制配置 FILEBROWSER_CURRENT_NAME;当前名称: diff --git a/rtdata/languages/Chinese (Traditional) b/rtdata/languages/Chinese (Traditional) index 2b2477748..d58343b6a 100644 --- a/rtdata/languages/Chinese (Traditional) +++ b/rtdata/languages/Chinese (Traditional) @@ -507,8 +507,6 @@ TP_WBALANCE_TEMPERATURE;色溫 !FILEBROWSER_BROWSEPATHBUTTONHINT;Click to browse to the chosen path. !FILEBROWSER_BROWSEPATHHINT;Type a path to navigate to.\n\nKeyboard shortcuts:\nCtrl-o to focus to the path text box.\nEnter / Ctrl-Enter to browse there;\nEsc to clear changes.\nShift-Esc to remove focus.\n\nPath shortcuts:\n~ - user's home directory.\n! - user's pictures directory !FILEBROWSER_CACHE;Cache -!FILEBROWSER_CACHECLEARFROMFULL;Clear from cache - full -!FILEBROWSER_CACHECLEARFROMPARTIAL;Clear from cache - partial !FILEBROWSER_COLORLABEL_TOOLTIP;Color label.\n\nUse dropdown menu or shortcuts:\nShift-Ctrl-0 No Color\nShift-Ctrl-1 Red\nShift-Ctrl-2 Yellow\nShift-Ctrl-3 Green\nShift-Ctrl-4 Blue\nShift-Ctrl-5 Purple !FILEBROWSER_CURRENT_NAME;Current name: !FILEBROWSER_DARKFRAME;Dark-frame diff --git a/rtdata/languages/Czech b/rtdata/languages/Czech index 18af7bf65..dbc606070 100644 --- a/rtdata/languages/Czech +++ b/rtdata/languages/Czech @@ -154,8 +154,6 @@ FILEBROWSER_AUTOFLATFIELD;Auto Flat Field FILEBROWSER_BROWSEPATHBUTTONHINT;Klikněte pro výběr cesty. FILEBROWSER_BROWSEPATHHINT;Vložte cestu pro procházení.\n\nKlávesové zkratky:\nCtrl-o pro přepnutí do adresního řádku.\nEnter/ Ctrl-Enter pro procházení ;\nEsc pro zrušení změn.\nShift-Esc pro zrušení přepnutí.\n\nZkratky pro cesty:\n~\t- domácí složka uživatele.\n!\t- složka s obrázky uživatele. FILEBROWSER_CACHE;Mezipaměť -FILEBROWSER_CACHECLEARFROMFULL;Vymazat z mezipaměti - úplně -FILEBROWSER_CACHECLEARFROMPARTIAL;Vymazat z mezipaměti - částečně FILEBROWSER_CLEARPROFILE;Smazat FILEBROWSER_COLORLABEL_TOOLTIP;Barevný štítek.\n\nPoužijte výběr ze seznamu nebo klávesové zkratky:\nShift-Ctrl-0 Bez barvy\nShift-Ctrl-1 Červený\nShift-Ctrl-2 Žlutý\nShift-Ctrl-3 Zelený\nShift-Ctrl-4 Modrý\nShift-Ctrl-5 Nachový FILEBROWSER_COPYPROFILE;Kopírovat diff --git a/rtdata/languages/Dansk b/rtdata/languages/Dansk index 547c5a6e6..da5616b31 100644 --- a/rtdata/languages/Dansk +++ b/rtdata/languages/Dansk @@ -499,8 +499,6 @@ TP_WBALANCE_TEMPERATURE;Temperatur !FILEBROWSER_BROWSEPATHBUTTONHINT;Click to browse to the chosen path. !FILEBROWSER_BROWSEPATHHINT;Type a path to navigate to.\n\nKeyboard shortcuts:\nCtrl-o to focus to the path text box.\nEnter / Ctrl-Enter to browse there;\nEsc to clear changes.\nShift-Esc to remove focus.\n\nPath shortcuts:\n~ - user's home directory.\n! - user's pictures directory !FILEBROWSER_CACHE;Cache -!FILEBROWSER_CACHECLEARFROMFULL;Clear from cache - full -!FILEBROWSER_CACHECLEARFROMPARTIAL;Clear from cache - partial !FILEBROWSER_COLORLABEL_TOOLTIP;Color label.\n\nUse dropdown menu or shortcuts:\nShift-Ctrl-0 No Color\nShift-Ctrl-1 Red\nShift-Ctrl-2 Yellow\nShift-Ctrl-3 Green\nShift-Ctrl-4 Blue\nShift-Ctrl-5 Purple !FILEBROWSER_CURRENT_NAME;Current name: !FILEBROWSER_DARKFRAME;Dark-frame diff --git a/rtdata/languages/Deutsch b/rtdata/languages/Deutsch index dd0655242..3cf1b32da 100644 --- a/rtdata/languages/Deutsch +++ b/rtdata/languages/Deutsch @@ -185,8 +185,6 @@ FILEBROWSER_AUTOFLATFIELD;Automatisches Weißbild FILEBROWSER_BROWSEPATHBUTTONHINT;Ausgewählten Pfad öffnen. FILEBROWSER_BROWSEPATHHINT;Einen Pfad eingeben:\nTaste:\nStrg + o Setzt den Cursor in das Eingabefeld\nEnter Öffnet den Pfad\nEsc Änderungen verwerfen\nUmschalt + Esc Eingabefeld verlassen\n\nSchnellnavigation:\nTaste:\n~ “Home“-Verzeichnis des Benutzers\n! Bilder-Verzeichnis des Benutzers FILEBROWSER_CACHE;Festplatten-Cache -FILEBROWSER_CACHECLEARFROMFULL;Aus dem Festplatten-Cache entfernen (vollständig) -FILEBROWSER_CACHECLEARFROMPARTIAL;Aus dem Festplatten-Cache entfernen (teilweise) FILEBROWSER_CLEARPROFILE;Profil löschen FILEBROWSER_COLORLABEL_TOOLTIP;Farbmarkierung\n\nTaste: Strg + Umschalt + 0 Ohne\nTaste: Strg + Umschalt + 1 Rot\nTaste: Strg + Umschalt + 2 Gelb\nTaste: Strg + Umschalt + 3 Grün\nTaste: Strg + Umschalt + 4 Blau\nTaste: Strg + Umschalt + 5 Violett FILEBROWSER_COPYPROFILE;Profil kopieren diff --git a/rtdata/languages/English (UK) b/rtdata/languages/English (UK) index 800e23527..8fcaafd56 100644 --- a/rtdata/languages/English (UK) +++ b/rtdata/languages/English (UK) @@ -232,8 +232,6 @@ TP_WBALANCE_EQBLUERED_TOOLTIP;Allows to deviate from the normal behaviour of "wh !FILEBROWSER_BROWSEPATHBUTTONHINT;Click to browse to the chosen path. !FILEBROWSER_BROWSEPATHHINT;Type a path to navigate to.\n\nKeyboard shortcuts:\nCtrl-o to focus to the path text box.\nEnter / Ctrl-Enter to browse there;\nEsc to clear changes.\nShift-Esc to remove focus.\n\nPath shortcuts:\n~ - user's home directory.\n! - user's pictures directory !FILEBROWSER_CACHE;Cache -!FILEBROWSER_CACHECLEARFROMFULL;Clear from cache - full -!FILEBROWSER_CACHECLEARFROMPARTIAL;Clear from cache - partial !FILEBROWSER_CLEARPROFILE;Clear !FILEBROWSER_COPYPROFILE;Copy !FILEBROWSER_CURRENT_NAME;Current name: diff --git a/rtdata/languages/English (US) b/rtdata/languages/English (US) index fc2fa83dd..53a2aec91 100644 --- a/rtdata/languages/English (US) +++ b/rtdata/languages/English (US) @@ -116,8 +116,6 @@ !FILEBROWSER_BROWSEPATHBUTTONHINT;Click to browse to the chosen path. !FILEBROWSER_BROWSEPATHHINT;Type a path to navigate to.\n\nKeyboard shortcuts:\nCtrl-o to focus to the path text box.\nEnter / Ctrl-Enter to browse there;\nEsc to clear changes.\nShift-Esc to remove focus.\n\nPath shortcuts:\n~ - user's home directory.\n! - user's pictures directory !FILEBROWSER_CACHE;Cache -!FILEBROWSER_CACHECLEARFROMFULL;Clear from cache - full -!FILEBROWSER_CACHECLEARFROMPARTIAL;Clear from cache - partial !FILEBROWSER_CLEARPROFILE;Clear !FILEBROWSER_COLORLABEL_TOOLTIP;Color label.\n\nUse dropdown menu or shortcuts:\nShift-Ctrl-0 No Color\nShift-Ctrl-1 Red\nShift-Ctrl-2 Yellow\nShift-Ctrl-3 Green\nShift-Ctrl-4 Blue\nShift-Ctrl-5 Purple !FILEBROWSER_COPYPROFILE;Copy diff --git a/rtdata/languages/Espanol b/rtdata/languages/Espanol index 5402f6579..4284523ab 100644 --- a/rtdata/languages/Espanol +++ b/rtdata/languages/Espanol @@ -149,8 +149,6 @@ FILEBROWSER_AUTOFLATFIELD;Campo plano automático FILEBROWSER_BROWSEPATHBUTTONHINT;Pulsar para examinar la carpeta seleccionada FILEBROWSER_BROWSEPATHHINT;Ingrese la ruta a examinar \nCtrl-O poner el foco en campo con la ruta\nEnter / Ctrl-Enter para examinar allí;\nEscPara quitar los cambios.\nShift-Esc Para quitar el foco.\n\n\nAbreviaturas de ruta:\n ~ - Carpeta hogar del usuario\n ! - Carpeta de imágenes del usuario FILEBROWSER_CACHE;Caché -FILEBROWSER_CACHECLEARFROMFULL;Limpiar del caché - Total -FILEBROWSER_CACHECLEARFROMPARTIAL;Limpiar del caché - Parcial FILEBROWSER_CLEARPROFILE;Borrar perfil FILEBROWSER_COLORLABEL_TOOLTIP;Etiquetar con color\n\nUse menú desplegable o atajos de teclado:\nShift-Ctrl-0 No Color\nShift-Ctrl-1 Rojo\nShift-Ctrl-2 Amarillo\nShift-Ctrl-3 Verde\nShift-Ctrl-4 Azul\nShift-Ctrl-5 Púrpura FILEBROWSER_COPYPROFILE;Copiar perfil diff --git a/rtdata/languages/Euskara b/rtdata/languages/Euskara index 851536a29..a604d6aef 100644 --- a/rtdata/languages/Euskara +++ b/rtdata/languages/Euskara @@ -500,8 +500,6 @@ TP_WBALANCE_TEMPERATURE;Tenperatura !FILEBROWSER_BROWSEPATHBUTTONHINT;Click to browse to the chosen path. !FILEBROWSER_BROWSEPATHHINT;Type a path to navigate to.\n\nKeyboard shortcuts:\nCtrl-o to focus to the path text box.\nEnter / Ctrl-Enter to browse there;\nEsc to clear changes.\nShift-Esc to remove focus.\n\nPath shortcuts:\n~ - user's home directory.\n! - user's pictures directory !FILEBROWSER_CACHE;Cache -!FILEBROWSER_CACHECLEARFROMFULL;Clear from cache - full -!FILEBROWSER_CACHECLEARFROMPARTIAL;Clear from cache - partial !FILEBROWSER_COLORLABEL_TOOLTIP;Color label.\n\nUse dropdown menu or shortcuts:\nShift-Ctrl-0 No Color\nShift-Ctrl-1 Red\nShift-Ctrl-2 Yellow\nShift-Ctrl-3 Green\nShift-Ctrl-4 Blue\nShift-Ctrl-5 Purple !FILEBROWSER_CURRENT_NAME;Current name: !FILEBROWSER_DARKFRAME;Dark-frame diff --git a/rtdata/languages/Francais b/rtdata/languages/Francais index 9c1fcce59..2bf82f6e1 100644 --- a/rtdata/languages/Francais +++ b/rtdata/languages/Francais @@ -111,8 +111,6 @@ FILEBROWSER_AUTOFLATFIELD;Champ Uniforme auto FILEBROWSER_BROWSEPATHBUTTONHINT;Cliquez pour parcourir le chemin saisi FILEBROWSER_BROWSEPATHHINT;Saisissez le chemin à parcourir\nCtrl-O pour placer le focus sur le champ de saisie.\nEntrée / Ctrl-Entrée pour y naviguer;\nEsc pour effacer les modifications.\nShift-Esc pour enlever le focus.\n\n\nRaccourcis pour les chemins:\n ~ - le dossier utilisateur\n ! - le dossier Images de l'utilisateur FILEBROWSER_CACHE;Cache -FILEBROWSER_CACHECLEARFROMFULL;Supprimer du cache (complet) -FILEBROWSER_CACHECLEARFROMPARTIAL;Supprimer du cache (partiel) FILEBROWSER_CLEARPROFILE;Remettre le profil à zéro FILEBROWSER_COLORLABEL_TOOLTIP;Label couleur\n\nUtilisez le menu déroulant ou le raccourci clavier:\nShift-Ctrl-0 Pas de couleur\nShift-Ctrl-1 Rouge\nShift-Ctrl-2 Jaune\nShift-Ctrl-3 Vert\nShift-Ctrl-4 Bleu\nShift-Ctrl-5 Pourpre FILEBROWSER_COPYPROFILE;Copier le profil diff --git a/rtdata/languages/Greek b/rtdata/languages/Greek index 086710b52..0c416e421 100644 --- a/rtdata/languages/Greek +++ b/rtdata/languages/Greek @@ -499,8 +499,6 @@ TP_WBALANCE_TEMPERATURE;Θερμοκρασία !FILEBROWSER_BROWSEPATHBUTTONHINT;Click to browse to the chosen path. !FILEBROWSER_BROWSEPATHHINT;Type a path to navigate to.\n\nKeyboard shortcuts:\nCtrl-o to focus to the path text box.\nEnter / Ctrl-Enter to browse there;\nEsc to clear changes.\nShift-Esc to remove focus.\n\nPath shortcuts:\n~ - user's home directory.\n! - user's pictures directory !FILEBROWSER_CACHE;Cache -!FILEBROWSER_CACHECLEARFROMFULL;Clear from cache - full -!FILEBROWSER_CACHECLEARFROMPARTIAL;Clear from cache - partial !FILEBROWSER_COLORLABEL_TOOLTIP;Color label.\n\nUse dropdown menu or shortcuts:\nShift-Ctrl-0 No Color\nShift-Ctrl-1 Red\nShift-Ctrl-2 Yellow\nShift-Ctrl-3 Green\nShift-Ctrl-4 Blue\nShift-Ctrl-5 Purple !FILEBROWSER_CURRENT_NAME;Current name: !FILEBROWSER_DARKFRAME;Dark-frame diff --git a/rtdata/languages/Hebrew b/rtdata/languages/Hebrew index c7477fd09..358045544 100644 --- a/rtdata/languages/Hebrew +++ b/rtdata/languages/Hebrew @@ -500,8 +500,6 @@ TP_WBALANCE_TEMPERATURE;מידת חום !FILEBROWSER_BROWSEPATHBUTTONHINT;Click to browse to the chosen path. !FILEBROWSER_BROWSEPATHHINT;Type a path to navigate to.\n\nKeyboard shortcuts:\nCtrl-o to focus to the path text box.\nEnter / Ctrl-Enter to browse there;\nEsc to clear changes.\nShift-Esc to remove focus.\n\nPath shortcuts:\n~ - user's home directory.\n! - user's pictures directory !FILEBROWSER_CACHE;Cache -!FILEBROWSER_CACHECLEARFROMFULL;Clear from cache - full -!FILEBROWSER_CACHECLEARFROMPARTIAL;Clear from cache - partial !FILEBROWSER_COLORLABEL_TOOLTIP;Color label.\n\nUse dropdown menu or shortcuts:\nShift-Ctrl-0 No Color\nShift-Ctrl-1 Red\nShift-Ctrl-2 Yellow\nShift-Ctrl-3 Green\nShift-Ctrl-4 Blue\nShift-Ctrl-5 Purple !FILEBROWSER_CURRENT_NAME;Current name: !FILEBROWSER_DARKFRAME;Dark-frame diff --git a/rtdata/languages/Italiano b/rtdata/languages/Italiano index ca048d956..e8a49771a 100644 --- a/rtdata/languages/Italiano +++ b/rtdata/languages/Italiano @@ -92,8 +92,6 @@ FILEBROWSER_AUTOFLATFIELD;Flat Field automatico FILEBROWSER_BROWSEPATHBUTTONHINT;Premi per aprire il percorso inserito FILEBROWSER_BROWSEPATHHINT;Inserisci il percorso da aprire\nCtrl-o seleziona il percorso\nEnter, Ctrl-Enter (solo nel Navigatore) porta alla destinazione ;\nScorciatoie:\n ~ - Cartella home\n ! - Cartella Immagini FILEBROWSER_CACHE;Memoria -FILEBROWSER_CACHECLEARFROMFULL;Rimuovi dalla memoria - totale -FILEBROWSER_CACHECLEARFROMPARTIAL;Rimuovi dalla memoria - parziale FILEBROWSER_CLEARPROFILE;Cancella FILEBROWSER_COLORLABEL_TOOLTIP;Etichetta colore.\n\nUsa il menù o le scorciatoie:\nShift-Ctrl-0 Nessun Colore\nShift-Ctrl-1 Rosso\nShift-Ctrl-2 Giallo\nShift-Ctrl-3 Verde\nShift-Ctrl-4 Blu\nShift-Ctrl-5 Viola FILEBROWSER_COPYPROFILE;Copia diff --git a/rtdata/languages/Japanese b/rtdata/languages/Japanese index fe8b79022..0bc015fe9 100644 --- a/rtdata/languages/Japanese +++ b/rtdata/languages/Japanese @@ -146,8 +146,6 @@ FILEBROWSER_AUTOFLATFIELD;オート・フラットフィールド FILEBROWSER_BROWSEPATHBUTTONHINT;クリックで選択したパスをブラウズ FILEBROWSER_BROWSEPATHHINT;参照するパスを入力します\nCtrl-O パスのテキストボックスにフォーカス\nEnter / Ctrl-Enterその場所をブラウズします\nEsc 変更をクリア\nShift-Escフォーカスを削除\nパスのショートカット:\n ~ - ユーザーのホームディレクトリ\n ! - ユーザーの画像ディレクトリ FILEBROWSER_CACHE;cache -FILEBROWSER_CACHECLEARFROMFULL;cacheをクリア - すべて -FILEBROWSER_CACHECLEARFROMPARTIAL;cacheをクリア - 一部 FILEBROWSER_CLEARPROFILE;プロファイルのクリア FILEBROWSER_COLORLABEL_TOOLTIP;カラー・ラベル\n\nドロップダウン・メニューからか、ショートカット:\nShift-Ctrl-1 レッド\nShift-Ctrl-2 イエロー\nShift-Ctrl-3 グリーン\nShift-Ctrl-4 ブルー\nShift-Ctrl-5 パープル FILEBROWSER_COPYPROFILE;プロファイルをコピー diff --git a/rtdata/languages/Latvian b/rtdata/languages/Latvian index 6689e4f95..23887cfb1 100644 --- a/rtdata/languages/Latvian +++ b/rtdata/languages/Latvian @@ -500,8 +500,6 @@ TP_WBALANCE_TEMPERATURE;Temperatūra !FILEBROWSER_BROWSEPATHBUTTONHINT;Click to browse to the chosen path. !FILEBROWSER_BROWSEPATHHINT;Type a path to navigate to.\n\nKeyboard shortcuts:\nCtrl-o to focus to the path text box.\nEnter / Ctrl-Enter to browse there;\nEsc to clear changes.\nShift-Esc to remove focus.\n\nPath shortcuts:\n~ - user's home directory.\n! - user's pictures directory !FILEBROWSER_CACHE;Cache -!FILEBROWSER_CACHECLEARFROMFULL;Clear from cache - full -!FILEBROWSER_CACHECLEARFROMPARTIAL;Clear from cache - partial !FILEBROWSER_COLORLABEL_TOOLTIP;Color label.\n\nUse dropdown menu or shortcuts:\nShift-Ctrl-0 No Color\nShift-Ctrl-1 Red\nShift-Ctrl-2 Yellow\nShift-Ctrl-3 Green\nShift-Ctrl-4 Blue\nShift-Ctrl-5 Purple !FILEBROWSER_CURRENT_NAME;Current name: !FILEBROWSER_DARKFRAME;Dark-frame diff --git a/rtdata/languages/Magyar b/rtdata/languages/Magyar index d0f806fea..4e463a8fd 100644 --- a/rtdata/languages/Magyar +++ b/rtdata/languages/Magyar @@ -82,8 +82,6 @@ FILEBROWSER_AUTOFLATFIELD;Auto Flat Field FILEBROWSER_BROWSEPATHBUTTONHINT;Kattints a kiválasztott útvonal böngészéséhez FILEBROWSER_BROWSEPATHHINT;Gépeld be az elérni kívánt útvonalat.\nCtrl-O-val tudod a fókuszt a beviteli mezőre vinni.\nEnter / Ctrl-Enter (az állományböngészőben) az ottani böngészéshez;\n\nÚtvonalrövidítések:\n ~ - felhasználói fiók (home) könyvtára\n - a felhasználó képkönyvtára FILEBROWSER_CACHE;Gyorsítótár -FILEBROWSER_CACHECLEARFROMFULL;Gyorsítótár ürítése - teljes -FILEBROWSER_CACHECLEARFROMPARTIAL;Gyorsítótár ürítése - részleges FILEBROWSER_CLEARPROFILE;Feldolgozási paraméter törlése FILEBROWSER_COPYPROFILE;Feldolgozási paraméterek másolása FILEBROWSER_CURRENT_NAME;Aktuális név: diff --git a/rtdata/languages/Nederlands b/rtdata/languages/Nederlands index f5948ef26..fd0036952 100644 --- a/rtdata/languages/Nederlands +++ b/rtdata/languages/Nederlands @@ -123,8 +123,6 @@ FILEBROWSER_AUTOFLATFIELD;Selecteer automatisch vlakveldopname FILEBROWSER_BROWSEPATHBUTTONHINT;Klik om te navigeren naar het gekozen pad FILEBROWSER_BROWSEPATHHINT;Typ het pad naar de doelmap.\nCtrl-O markeer het pad in het tekstveld.\nEnter / Ctrl-Enter open de map.\nEsc maak het tekstveld leeg.\nShift-Esc verwijder markering.\n\n\nSneltoetsen:\n ~ - gebruikers home directory\n ! - gebruikers afbeeldingen map FILEBROWSER_CACHE;Cache -FILEBROWSER_CACHECLEARFROMFULL;Verwijder uit cache - volledig -FILEBROWSER_CACHECLEARFROMPARTIAL;Verwijder uit cache - gedeeltelijk FILEBROWSER_CLEARPROFILE;Verwijder profiel FILEBROWSER_COLORLABEL_TOOLTIP;Kleur label\n\nGebruik keuzemenu of nSneltoets:\nShift-Ctrl-0 Geen kleur\nShift-Ctrl-1 Rood\nShift-Ctrl-2 Geel\nShift-Ctrl-3 Groen\nShift-Ctrl-4 Blauw\nShift-Ctrl-5 Paars FILEBROWSER_COPYPROFILE;Kopieer profiel diff --git a/rtdata/languages/Norsk BM b/rtdata/languages/Norsk BM index 4a76fdcda..4a4995aef 100644 --- a/rtdata/languages/Norsk BM +++ b/rtdata/languages/Norsk BM @@ -499,8 +499,6 @@ TP_WBALANCE_TEMPERATURE;Temperatur !FILEBROWSER_BROWSEPATHBUTTONHINT;Click to browse to the chosen path. !FILEBROWSER_BROWSEPATHHINT;Type a path to navigate to.\n\nKeyboard shortcuts:\nCtrl-o to focus to the path text box.\nEnter / Ctrl-Enter to browse there;\nEsc to clear changes.\nShift-Esc to remove focus.\n\nPath shortcuts:\n~ - user's home directory.\n! - user's pictures directory !FILEBROWSER_CACHE;Cache -!FILEBROWSER_CACHECLEARFROMFULL;Clear from cache - full -!FILEBROWSER_CACHECLEARFROMPARTIAL;Clear from cache - partial !FILEBROWSER_COLORLABEL_TOOLTIP;Color label.\n\nUse dropdown menu or shortcuts:\nShift-Ctrl-0 No Color\nShift-Ctrl-1 Red\nShift-Ctrl-2 Yellow\nShift-Ctrl-3 Green\nShift-Ctrl-4 Blue\nShift-Ctrl-5 Purple !FILEBROWSER_CURRENT_NAME;Current name: !FILEBROWSER_DARKFRAME;Dark-frame diff --git a/rtdata/languages/Polish b/rtdata/languages/Polish index f54de5593..b271178e0 100644 --- a/rtdata/languages/Polish +++ b/rtdata/languages/Polish @@ -96,8 +96,6 @@ FILEBROWSER_AUTOFLATFIELD;Automatyczne użycie klatki typu puste pole FILEBROWSER_BROWSEPATHBUTTONHINT;Należy kliknąć, aby przeglądać wybraną ścieżkę FILEBROWSER_BROWSEPATHHINT;Umożliwia przeglądanie wprowadzonej ścieżki\nCtrl-o zaznaczenie\nEnter, Ctrl-Enter (w menedżerze plików) przeglądanie\nSkróty:\n ~ - katalog domowy użytkownika\n ! - katalog z obrazami użytkownia FILEBROWSER_CACHE;Pamięć podręczna -FILEBROWSER_CACHECLEARFROMFULL;Czyszczenie pamięci podręcznej - pełne -FILEBROWSER_CACHECLEARFROMPARTIAL;Czyszczenie pamięci podręcznej - częściowe FILEBROWSER_CLEARPROFILE;Wyczyść profil FILEBROWSER_COLORLABEL_TOOLTIP;Kolorowe etykiety\n\nUżyj za pomocą rozwijanej listy lub skrótów:\nShift-Ctrl-0 No Color\nShift-Ctrl-1 Czerwona\nShift-Ctrl-2 Żółta\nShift-Ctrl-3 Zielona\nShift-Ctrl-4 Niebieska\nShift-Ctrl-5 Purpurowa FILEBROWSER_COPYPROFILE;Kopiuj profil diff --git a/rtdata/languages/Polish (Latin Characters) b/rtdata/languages/Polish (Latin Characters) index d3e62a777..310a1ed13 100644 --- a/rtdata/languages/Polish (Latin Characters) +++ b/rtdata/languages/Polish (Latin Characters) @@ -96,8 +96,6 @@ FILEBROWSER_AUTOFLATFIELD;Automatyczne uzycie klatki typu puste pole FILEBROWSER_BROWSEPATHBUTTONHINT;Nalezy kliknac, aby przegladac wybrana sciezke FILEBROWSER_BROWSEPATHHINT;Umozliwia przegladanie wprowadzonej sciezki\nCtrl-o zaznaczenie\nEnter, Ctrl-Enter (w menedzerze plikow) przegladanie\nSkroty:\n ~ - katalog domowy uzytkownika\n ! - katalog z obrazami uzytkownia FILEBROWSER_CACHE;Pamiec podreczna -FILEBROWSER_CACHECLEARFROMFULL;Czyszczenie pamieci podrecznej - pelne -FILEBROWSER_CACHECLEARFROMPARTIAL;Czyszczenie pamieci podrecznej - czesciowe FILEBROWSER_CLEARPROFILE;Wyczysc profil FILEBROWSER_COLORLABEL_TOOLTIP;Kolorowe etykiety\n\nUzyj za pomoca rozwijanej listy lub skrotow:\nShift-Ctrl-0 No Color\nShift-Ctrl-1 Czerwona\nShift-Ctrl-2 Zolta\nShift-Ctrl-3 Zielona\nShift-Ctrl-4 Niebieska\nShift-Ctrl-5 Purpurowa FILEBROWSER_COPYPROFILE;Kopiuj profil diff --git a/rtdata/languages/Portugues (Brasil) b/rtdata/languages/Portugues (Brasil) index 7acb91cce..c737ddcfd 100644 --- a/rtdata/languages/Portugues (Brasil) +++ b/rtdata/languages/Portugues (Brasil) @@ -113,8 +113,6 @@ FILEBROWSER_AUTOFLATFIELD;Flat-field automático FILEBROWSER_BROWSEPATHBUTTONHINT;Clique para navegar até o caminho escolhido. FILEBROWSER_BROWSEPATHHINT;Digite um caminho para navegar até.\n\nAtalhos do teclado:\nCtrl-o para focar na caixa de texto do caminho.\nEnter / Ctrl-Enter para navegar lá;\nEsc para limpar as alterações.\nShift-Esc para remover o foco.\n\nAtalhos do caminho:\n~ - diretório home do usuário.\n! - diretório de fotos do usuário FILEBROWSER_CACHE;Cache -FILEBROWSER_CACHECLEARFROMFULL;Limpeza do cache - completa -FILEBROWSER_CACHECLEARFROMPARTIAL;Limpeza do cache - partcial FILEBROWSER_CLEARPROFILE;Perfil de limpeza FILEBROWSER_COLORLABEL_TOOLTIP;Etiqueta de cor.\n\nUse o menu suspenso ou atalhos:\nShift-Ctrl-0 Sem Cor\nShift-Ctrl-1 Vermelho\nShift-Ctrl-2 Amarelo\nShift-Ctrl-3 Verde\nShift-Ctrl-4 Azul\nShift-Ctrl-5 Roxo FILEBROWSER_COPYPROFILE;Copiar perfil diff --git a/rtdata/languages/Russian b/rtdata/languages/Russian index 36b63772e..3c89c4a74 100644 --- a/rtdata/languages/Russian +++ b/rtdata/languages/Russian @@ -105,8 +105,6 @@ FILEBROWSER_AUTOFLATFIELD;Автоматическое плоское поле FILEBROWSER_BROWSEPATHBUTTONHINT;Нажмите кнопку мыши чтобы перейти к выбранному каталогу FILEBROWSER_BROWSEPATHHINT;Введите путь для перехода.\nCtrl-O для перехода на диалог ввода текста.\nEnter / Ctrl-Enter (в обозревателе файлов) для перехода;\n\nЯрлыки путей:\n ~ - домашняя папка пользователя\n ! - папка пользователя с изображениями FILEBROWSER_CACHE;Кэш -FILEBROWSER_CACHECLEARFROMFULL;Удалить из кэша - полностью -FILEBROWSER_CACHECLEARFROMPARTIAL;Удалить из кэша - частично FILEBROWSER_CLEARPROFILE;Удалить профиль FILEBROWSER_COLORLABEL_TOOLTIP;Color label\n\nUse dropdown menu or Shortcuts:\nShift-Ctrl-0 No Color\nShift-Ctrl-1 Red\nShift-Ctrl-2 Yellow\nShift-Ctrl-3 Green\nShift-Ctrl-4 Blue\nShift-Ctrl-5 Purple FILEBROWSER_COPYPROFILE;Скопировать профиль diff --git a/rtdata/languages/Serbian (Cyrilic Characters) b/rtdata/languages/Serbian (Cyrilic Characters) index e69c9b874..34c62bf06 100644 --- a/rtdata/languages/Serbian (Cyrilic Characters) +++ b/rtdata/languages/Serbian (Cyrilic Characters) @@ -85,8 +85,6 @@ FILEBROWSER_AUTOFLATFIELD;Аутоматски одреди равно поље FILEBROWSER_BROWSEPATHBUTTONHINT;Кликните за одлазак на узабрану путању FILEBROWSER_BROWSEPATHHINT;Укуцајте путању за разгледање (Ctrl-o поставља фокус, Ctrl-Enter приказује у разгледачу датотека);nПречице путања: ~ — лични директоријум, ! — директоријум са сликама FILEBROWSER_CACHE;Остава -FILEBROWSER_CACHECLEARFROMFULL;Очисти из оставе — све -FILEBROWSER_CACHECLEARFROMPARTIAL;Очисти из оставе — половично FILEBROWSER_CLEARPROFILE;Обриши профил FILEBROWSER_COLORLABEL_TOOLTIP;Натпис у боји.\n\nКористите приложени мени или пречице:\nShift-Ctrl-0 Без боје\nShift-Ctrl-1 Црвена\nShift-Ctrl-2 Жута\nShift-Ctrl-3 Зелена\nShift-Ctrl-4 Плана\nShift-Ctrl-5 Љубичаста FILEBROWSER_COPYPROFILE;Умножи профил diff --git a/rtdata/languages/Serbian (Latin Characters) b/rtdata/languages/Serbian (Latin Characters) index 727cdeb9a..5dd1fa04d 100644 --- a/rtdata/languages/Serbian (Latin Characters) +++ b/rtdata/languages/Serbian (Latin Characters) @@ -85,8 +85,6 @@ FILEBROWSER_AUTOFLATFIELD;Automatski odredi ravno polje FILEBROWSER_BROWSEPATHBUTTONHINT;Kliknite za odlazak na uzabranu putanju FILEBROWSER_BROWSEPATHHINT;Ukucajte putanju za razgledanje (Ctrl-o postavlja fokus, Ctrl-Enter prikazuje u razgledaču datoteka);nPrečice putanja: ~ — lični direktorijum, ! — direktorijum sa slikama FILEBROWSER_CACHE;Ostava -FILEBROWSER_CACHECLEARFROMFULL;Očisti iz ostave — sve -FILEBROWSER_CACHECLEARFROMPARTIAL;Očisti iz ostave — polovično FILEBROWSER_CLEARPROFILE;Obriši profil FILEBROWSER_COLORLABEL_TOOLTIP;Natpis u boji.\n\nKoristite priloženi meni ili prečice:\nShift-Ctrl-0 Bez boje\nShift-Ctrl-1 Crvena\nShift-Ctrl-2 Žuta\nShift-Ctrl-3 Zelena\nShift-Ctrl-4 Plana\nShift-Ctrl-5 Ljubičasta FILEBROWSER_COPYPROFILE;Umnoži profil diff --git a/rtdata/languages/Slovak b/rtdata/languages/Slovak index 022c715e3..15c4050ad 100644 --- a/rtdata/languages/Slovak +++ b/rtdata/languages/Slovak @@ -578,8 +578,6 @@ ZOOMPANEL_ZOOMOUT;Oddialiť - !FILEBROWSER_BROWSEPATHBUTTONHINT;Click to browse to the chosen path. !FILEBROWSER_BROWSEPATHHINT;Type a path to navigate to.\n\nKeyboard shortcuts:\nCtrl-o to focus to the path text box.\nEnter / Ctrl-Enter to browse there;\nEsc to clear changes.\nShift-Esc to remove focus.\n\nPath shortcuts:\n~ - user's home directory.\n! - user's pictures directory !FILEBROWSER_CACHE;Cache -!FILEBROWSER_CACHECLEARFROMFULL;Clear from cache - full -!FILEBROWSER_CACHECLEARFROMPARTIAL;Clear from cache - partial !FILEBROWSER_COLORLABEL_TOOLTIP;Color label.\n\nUse dropdown menu or shortcuts:\nShift-Ctrl-0 No Color\nShift-Ctrl-1 Red\nShift-Ctrl-2 Yellow\nShift-Ctrl-3 Green\nShift-Ctrl-4 Blue\nShift-Ctrl-5 Purple !FILEBROWSER_DARKFRAME;Dark-frame !FILEBROWSER_DELETEDLGMSGINCLPROC;Are you sure you want to delete the selected %1 files including a queue-processed version? diff --git a/rtdata/languages/Suomi b/rtdata/languages/Suomi index 722bf1b0b..b0d075188 100644 --- a/rtdata/languages/Suomi +++ b/rtdata/languages/Suomi @@ -501,8 +501,6 @@ TP_WBALANCE_TEMPERATURE;Lämpötila [K] !FILEBROWSER_BROWSEPATHBUTTONHINT;Click to browse to the chosen path. !FILEBROWSER_BROWSEPATHHINT;Type a path to navigate to.\n\nKeyboard shortcuts:\nCtrl-o to focus to the path text box.\nEnter / Ctrl-Enter to browse there;\nEsc to clear changes.\nShift-Esc to remove focus.\n\nPath shortcuts:\n~ - user's home directory.\n! - user's pictures directory !FILEBROWSER_CACHE;Cache -!FILEBROWSER_CACHECLEARFROMFULL;Clear from cache - full -!FILEBROWSER_CACHECLEARFROMPARTIAL;Clear from cache - partial !FILEBROWSER_COLORLABEL_TOOLTIP;Color label.\n\nUse dropdown menu or shortcuts:\nShift-Ctrl-0 No Color\nShift-Ctrl-1 Red\nShift-Ctrl-2 Yellow\nShift-Ctrl-3 Green\nShift-Ctrl-4 Blue\nShift-Ctrl-5 Purple !FILEBROWSER_CURRENT_NAME;Current name: !FILEBROWSER_DARKFRAME;Dark-frame diff --git a/rtdata/languages/Swedish b/rtdata/languages/Swedish index 44c5dd475..82b11df1e 100644 --- a/rtdata/languages/Swedish +++ b/rtdata/languages/Swedish @@ -94,8 +94,6 @@ FILEBROWSER_AUTOFLATFIELD;Automatisk plattfältskorrigering FILEBROWSER_BROWSEPATHBUTTONHINT;Klicka för att komma till vald sökväg FILEBROWSER_BROWSEPATHHINT;Skriv in en sökväg och tryck Enter (Ctrl-Enter i filhanteraren).\nCtrl-O för att komma till sökfältet.\nEnter / Ctrl-Enter för att bläddra;\nEsc för att rensa ändringar.\nShift-Esc för att ta bort fokus från sökfältet.\n\n\nPath kortkommando:\n ~ - användarens hemkatalog\n ! - användarens bildkatalog FILEBROWSER_CACHE;Cache -FILEBROWSER_CACHECLEARFROMFULL;Rensa från cachen - fullständigt -FILEBROWSER_CACHECLEARFROMPARTIAL;Rensa från cachen - delvis FILEBROWSER_CLEARPROFILE;Återställ profilen FILEBROWSER_COLORLABEL_TOOLTIP;Färgetikett\n\nAnvänd menyn eller kortkommandona:\nShift-Ctrl-0 No Color\nShift-Ctrl-1 Röd\nShift-Ctrl-2 Gul\nShift-Ctrl-3 Grön\nShift-Ctrl-4 Blå\nShift-Ctrl-5 Lila FILEBROWSER_COPYPROFILE;Kopiera profil diff --git a/rtdata/languages/Turkish b/rtdata/languages/Turkish index a3dd1d5ea..051c99217 100644 --- a/rtdata/languages/Turkish +++ b/rtdata/languages/Turkish @@ -500,8 +500,6 @@ TP_WBALANCE_TEMPERATURE;Isı !FILEBROWSER_BROWSEPATHBUTTONHINT;Click to browse to the chosen path. !FILEBROWSER_BROWSEPATHHINT;Type a path to navigate to.\n\nKeyboard shortcuts:\nCtrl-o to focus to the path text box.\nEnter / Ctrl-Enter to browse there;\nEsc to clear changes.\nShift-Esc to remove focus.\n\nPath shortcuts:\n~ - user's home directory.\n! - user's pictures directory !FILEBROWSER_CACHE;Cache -!FILEBROWSER_CACHECLEARFROMFULL;Clear from cache - full -!FILEBROWSER_CACHECLEARFROMPARTIAL;Clear from cache - partial !FILEBROWSER_COLORLABEL_TOOLTIP;Color label.\n\nUse dropdown menu or shortcuts:\nShift-Ctrl-0 No Color\nShift-Ctrl-1 Red\nShift-Ctrl-2 Yellow\nShift-Ctrl-3 Green\nShift-Ctrl-4 Blue\nShift-Ctrl-5 Purple !FILEBROWSER_CURRENT_NAME;Current name: !FILEBROWSER_DARKFRAME;Dark-frame diff --git a/rtdata/languages/default b/rtdata/languages/default index dd5c7e697..be311113f 100644 --- a/rtdata/languages/default +++ b/rtdata/languages/default @@ -119,8 +119,8 @@ FILEBROWSER_AUTOFLATFIELD;Auto flat-field FILEBROWSER_BROWSEPATHBUTTONHINT;Click to browse to the chosen path. FILEBROWSER_BROWSEPATHHINT;Type a path to navigate to.\n\nKeyboard shortcuts:\nCtrl-o to focus to the path text box.\nEnter / Ctrl-Enter to browse there;\nEsc to clear changes.\nShift-Esc to remove focus.\n\nPath shortcuts:\n~ - user's home directory.\n! - user's pictures directory FILEBROWSER_CACHE;Cache -FILEBROWSER_CACHECLEARFROMFULL;Clear from cache - full -FILEBROWSER_CACHECLEARFROMPARTIAL;Clear from cache - partial +FILEBROWSER_CACHECLEARFROMFULL;Clear all except cached profiles +FILEBROWSER_CACHECLEARFROMPARTIAL;Clear all including cached profiles FILEBROWSER_CLEARPROFILE;Clear FILEBROWSER_COLORLABEL_TOOLTIP;Color label.\n\nUse dropdown menu or shortcuts:\nShift-Ctrl-0 No Color\nShift-Ctrl-1 Red\nShift-Ctrl-2 Yellow\nShift-Ctrl-3 Green\nShift-Ctrl-4 Blue\nShift-Ctrl-5 Purple FILEBROWSER_COPYPROFILE;Copy From 9a4d770faacfb33bd5061907116d22d534b66423 Mon Sep 17 00:00:00 2001 From: Morgan Hardwood Date: Wed, 31 Oct 2018 22:40:45 +0100 Subject: [PATCH 41/42] Fixing swapped labels --- rtdata/languages/default | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rtdata/languages/default b/rtdata/languages/default index be311113f..1a1d4a18b 100644 --- a/rtdata/languages/default +++ b/rtdata/languages/default @@ -119,8 +119,8 @@ FILEBROWSER_AUTOFLATFIELD;Auto flat-field FILEBROWSER_BROWSEPATHBUTTONHINT;Click to browse to the chosen path. FILEBROWSER_BROWSEPATHHINT;Type a path to navigate to.\n\nKeyboard shortcuts:\nCtrl-o to focus to the path text box.\nEnter / Ctrl-Enter to browse there;\nEsc to clear changes.\nShift-Esc to remove focus.\n\nPath shortcuts:\n~ - user's home directory.\n! - user's pictures directory FILEBROWSER_CACHE;Cache -FILEBROWSER_CACHECLEARFROMFULL;Clear all except cached profiles -FILEBROWSER_CACHECLEARFROMPARTIAL;Clear all including cached profiles +FILEBROWSER_CACHECLEARFROMFULL;Clear all including cached profiles +FILEBROWSER_CACHECLEARFROMPARTIAL;Clear all except cached profiles FILEBROWSER_CLEARPROFILE;Clear FILEBROWSER_COLORLABEL_TOOLTIP;Color label.\n\nUse dropdown menu or shortcuts:\nShift-Ctrl-0 No Color\nShift-Ctrl-1 Red\nShift-Ctrl-2 Yellow\nShift-Ctrl-3 Green\nShift-Ctrl-4 Blue\nShift-Ctrl-5 Purple FILEBROWSER_COPYPROFILE;Copy From 86b282fc688f50df4a8232eed8bb60f2205a49c9 Mon Sep 17 00:00:00 2001 From: Alberto Griggio Date: Thu, 1 Nov 2018 05:42:45 +0100 Subject: [PATCH 42/42] procparams: call DehazeParams::operator== in ProcParams::operator== --- rtengine/procparams.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/rtengine/procparams.cc b/rtengine/procparams.cc index 64440d222..4a3310fb4 100644 --- a/rtengine/procparams.cc +++ b/rtengine/procparams.cc @@ -5073,7 +5073,8 @@ bool ProcParams::operator ==(const ProcParams& other) const && colorToning == other.colorToning && metadata == other.metadata && exif == other.exif - && iptc == other.iptc; + && iptc == other.iptc + && dehaze == other.dehaze; } bool ProcParams::operator !=(const ProcParams& other) const