From 5d5c51d200b43a23adc289c42da27c6ac68c7dc0 Mon Sep 17 00:00:00 2001 From: Alberto Griggio Date: Wed, 7 Feb 2018 09:34:19 +0100 Subject: [PATCH 01/42] added support for user-specific DCP and input ICC profiles dirs Look for direcories dcpprofiles/ and iccprofiles/input/ under Options::rtdir (typically something like $HOME/.config/RawTherapee) --- rtengine/dcp.cc | 73 ++++++++++++++++++++++---------------------- rtengine/dcp.h | 2 +- rtengine/iccstore.cc | 2 ++ 3 files changed, 40 insertions(+), 37 deletions(-) diff --git a/rtengine/dcp.cc b/rtengine/dcp.cc index fe798cb99..01929c9db 100644 --- a/rtengine/dcp.cc +++ b/rtengine/dcp.cc @@ -1737,51 +1737,50 @@ void DCPStore::init(const Glib::ustring& rt_profile_dir, bool loadAll) file_std_profiles.clear(); if (!loadAll) { - profileDir.assign (rt_profile_dir); + profileDir = { rt_profile_dir, Glib::build_filename(options.rtdir, "dcpprofiles") }; return; } - if (!rt_profile_dir.empty()) { - std::deque dirs = { - rt_profile_dir - }; + std::deque dirs = { + rt_profile_dir, + Glib::build_filename(options.rtdir, "dcpprofiles") + }; - while (!dirs.empty()) { - // Process directory - Glib::ustring dirname = dirs.back(); - dirs.pop_back(); + while (!dirs.empty()) { + // Process directory + Glib::ustring dirname = dirs.back(); + dirs.pop_back(); - std::unique_ptr dir; + std::unique_ptr dir; - try { - if (!Glib::file_test(dirname, Glib::FILE_TEST_IS_DIR)) { - return; - } - - dir.reset(new Glib::Dir(dirname)); - } catch (Glib::Exception& exception) { + try { + if (!Glib::file_test(dirname, Glib::FILE_TEST_IS_DIR)) { return; } - for (const Glib::ustring& sname : *dir) { - const Glib::ustring fname = Glib::build_filename(dirname, sname); + dir.reset(new Glib::Dir(dirname)); + } catch (Glib::Exception& exception) { + return; + } - if (!Glib::file_test(fname, Glib::FILE_TEST_IS_DIR)) { - // File - const auto lastdot = sname.rfind('.'); + for (const Glib::ustring& sname : *dir) { + const Glib::ustring fname = Glib::build_filename(dirname, sname); - if ( - lastdot != Glib::ustring::npos - && lastdot <= sname.size() - 4 - && !sname.casefold().compare(lastdot, 4, ".dcp") + if (!Glib::file_test(fname, Glib::FILE_TEST_IS_DIR)) { + // File + const auto lastdot = sname.rfind('.'); + + if ( + lastdot != Glib::ustring::npos + && lastdot <= sname.size() - 4 + && !sname.casefold().compare(lastdot, 4, ".dcp") ) { - const Glib::ustring cam_short_name = sname.substr(0, lastdot).uppercase(); - file_std_profiles[cam_short_name] = fname; // They will be loaded and cached on demand - } - } else { - // Directory - dirs.push_front(fname); + const Glib::ustring cam_short_name = sname.substr(0, lastdot).uppercase(); + file_std_profiles[cam_short_name] = fname; // They will be loaded and cached on demand } + } else { + // Directory + dirs.push_front(fname); } } } @@ -1839,11 +1838,13 @@ DCPProfile* DCPStore::getStdProfile(const Glib::ustring& requested_cam_short_nam } // profile not found, looking if we're in loadAll=false mode - if (!profileDir.empty()) { - const Glib::ustring fname = Glib::build_filename(profileDir, requested_cam_short_name + Glib::ustring(".dcp")); + for (const auto &dir : profileDir) { + if (!dir.empty()) { + const Glib::ustring fname = Glib::build_filename(dir, requested_cam_short_name + Glib::ustring(".dcp")); - if (Glib::file_test(fname, Glib::FILE_TEST_EXISTS)) { - return getProfile(fname); + if (Glib::file_test(fname, Glib::FILE_TEST_EXISTS)) { + return getProfile(fname); + } } } diff --git a/rtengine/dcp.h b/rtengine/dcp.h index 10bbf8f7e..bedc7f76d 100644 --- a/rtengine/dcp.h +++ b/rtengine/dcp.h @@ -166,7 +166,7 @@ private: DCPStore() = default; mutable MyMutex mutex; - Glib::ustring profileDir; + std::vector profileDir; // these contain standard profiles from RT. keys are all in uppercase, file path is value std::map file_std_profiles; diff --git a/rtengine/iccstore.cc b/rtengine/iccstore.cc index 50ff58878..51c77b719 100644 --- a/rtengine/iccstore.cc +++ b/rtengine/iccstore.cc @@ -334,6 +334,8 @@ public: fileStdProfilesFileNames.clear(); if (loadAll) { loadProfiles(stdProfilesDir, nullptr, nullptr, &fileStdProfilesFileNames, true); + Glib::ustring user_input_icc_dir = Glib::build_filename(options.rtdir, "iccprofiles", "input"); + loadProfiles(user_input_icc_dir, nullptr, nullptr, &fileStdProfilesFileNames, true); } defaultMonitorProfile = settings->monitorProfile; From 66bbab9ae2d9f9cdd1dceeef53710eda0957c1e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fl=C3=B6ssie?= Date: Wed, 16 May 2018 19:53:10 +0200 Subject: [PATCH 02/42] Sort file numbers naturally (#2467) --- rtgui/thumbbrowserentrybase.cc | 149 ++++++++++++++++++++++++++++++++- 1 file changed, 148 insertions(+), 1 deletion(-) diff --git a/rtgui/thumbbrowserentrybase.cc b/rtgui/thumbbrowserentrybase.cc index 2fff95904..bc9506e3f 100644 --- a/rtgui/thumbbrowserentrybase.cc +++ b/rtgui/thumbbrowserentrybase.cc @@ -23,6 +23,153 @@ #include "../rtengine/mytime.h" +namespace +{ + +Glib::ustring getPaddedName(const Glib::ustring& name) +{ + enum class State { + OTHER, + NUMBER, + FRACTION + }; + + constexpr unsigned int pad_width = 17; // Must be at least 1 + + Glib::ustring res; + + State state = State::OTHER; + Glib::ustring number; + + for (auto c : name) { + switch (state) { + case State::OTHER: { + switch (c) { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': { + number += c; + state = State::NUMBER; + break; + } + + case '.': { + res += c; + state = State::FRACTION; + break; + } + + default: { + res += c; + break; + } + } + break; + } + + case State::NUMBER: { + switch (c) { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': { + number += c; + break; + } + + default: { + if (number.size() < pad_width) { + res.append(pad_width - number.size(), '0'); + } + res += number; + res += c; + number.clear(); + + state = + c == '.' + ? State::FRACTION + : State::OTHER; + break; + } + } + break; + } + + case State::FRACTION: { + switch (c) { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': { + number += c; + break; + } + + default: { + res += number; + if (!number.empty() && number.size() < pad_width) { + res.append(pad_width - number.size(), '0'); + } + res += c; + number.clear(); + + if (c != '.') { + state = State::OTHER; + } + break; + } + } + break; + } + } + } + + switch (state) { + case State::OTHER: { + break; + } + + case State::NUMBER: { + if (number.size() < pad_width) { + res.append(pad_width - number.size(), '0'); + } + res += number; + break; + } + + case State::FRACTION: { + res += number; + if (!number.empty() && number.size() < pad_width) { + res.append(pad_width - number.size(), '0'); + } + break; + } + } + + return res; +} + +} + ThumbBrowserEntryBase::ThumbBrowserEntryBase (const Glib::ustring& fname) : fnlabw(0), fnlabh(0), @@ -57,7 +204,7 @@ ThumbBrowserEntryBase::ThumbBrowserEntryBase (const Glib::ustring& fname) : bbFramed(false), bbPreview(nullptr), cursor_type(CSUndefined), - collate_name(dispname.casefold().collate_key()), + collate_name(getPaddedName(dispname).casefold_collate_key()), thumbnail(nullptr), filename(fname), shortname(dispname), From 70eefd049b4eb5a50907de65a02f345472583d65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fl=C3=B6ssie?= Date: Wed, 16 May 2018 20:09:39 +0200 Subject: [PATCH 03/42] Tidy negative number parsing relict --- rtgui/thumbbrowserentrybase.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rtgui/thumbbrowserentrybase.cc b/rtgui/thumbbrowserentrybase.cc index bc9506e3f..dbab6837b 100644 --- a/rtgui/thumbbrowserentrybase.cc +++ b/rtgui/thumbbrowserentrybase.cc @@ -34,7 +34,7 @@ Glib::ustring getPaddedName(const Glib::ustring& name) FRACTION }; - constexpr unsigned int pad_width = 17; // Must be at least 1 + constexpr unsigned int pad_width = 16; Glib::ustring res; From 579aae510c8c112f7f40ba525d6f89b9717627ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fl=C3=B6ssie?= Date: Fri, 18 May 2018 20:00:40 +0200 Subject: [PATCH 04/42] Consider integers only (#2467) --- rtgui/thumbbrowserentrybase.cc | 56 ++-------------------------------- 1 file changed, 3 insertions(+), 53 deletions(-) diff --git a/rtgui/thumbbrowserentrybase.cc b/rtgui/thumbbrowserentrybase.cc index dbab6837b..34557ccc4 100644 --- a/rtgui/thumbbrowserentrybase.cc +++ b/rtgui/thumbbrowserentrybase.cc @@ -30,8 +30,7 @@ Glib::ustring getPaddedName(const Glib::ustring& name) { enum class State { OTHER, - NUMBER, - FRACTION + NUMBER }; constexpr unsigned int pad_width = 16; @@ -56,13 +55,8 @@ Glib::ustring getPaddedName(const Glib::ustring& name) case '8': case '9': { number += c; - state = State::NUMBER; - break; - } - case '.': { - res += c; - state = State::FRACTION; + state = State::NUMBER; break; } @@ -98,43 +92,7 @@ Glib::ustring getPaddedName(const Glib::ustring& name) res += c; number.clear(); - state = - c == '.' - ? State::FRACTION - : State::OTHER; - break; - } - } - break; - } - - case State::FRACTION: { - switch (c) { - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': { - number += c; - break; - } - - default: { - res += number; - if (!number.empty() && number.size() < pad_width) { - res.append(pad_width - number.size(), '0'); - } - res += c; - number.clear(); - - if (c != '.') { - state = State::OTHER; - } + state = State::OTHER; break; } } @@ -155,14 +113,6 @@ Glib::ustring getPaddedName(const Glib::ustring& name) res += number; break; } - - case State::FRACTION: { - res += number; - if (!number.empty() && number.size() < pad_width) { - res.append(pad_width - number.size(), '0'); - } - break; - } } return res; From 710dd13c2f98f1dea82f7c5290b589c9a33c4ee0 Mon Sep 17 00:00:00 2001 From: heckflosse Date: Tue, 29 May 2018 15:00:33 +0200 Subject: [PATCH 05/42] First version of combined amaze/vng4 demosaic --- rtengine/CMakeLists.txt | 1 + rtengine/amaze_vng4_demosaic_RT.cc | 171 +++++++++++++++++++++++++++++ rtengine/rawimagesource.cc | 3 +- rtengine/rawimagesource.h | 1 + 4 files changed, 175 insertions(+), 1 deletion(-) create mode 100644 rtengine/amaze_vng4_demosaic_RT.cc diff --git a/rtengine/CMakeLists.txt b/rtengine/CMakeLists.txt index 5ecd458be..b12fa5e46 100644 --- a/rtengine/CMakeLists.txt +++ b/rtengine/CMakeLists.txt @@ -33,6 +33,7 @@ set(RTENGINESOURCEFILES FTblockDN.cc PF_correct_RT.cc amaze_demosaic_RT.cc + amaze_vng4_demosaic_RT.cc cJSON.c calc_distort.cc camconst.cc diff --git a/rtengine/amaze_vng4_demosaic_RT.cc b/rtengine/amaze_vng4_demosaic_RT.cc new file mode 100644 index 000000000..f6b109bb6 --- /dev/null +++ b/rtengine/amaze_vng4_demosaic_RT.cc @@ -0,0 +1,171 @@ +//////////////////////////////////////////////////////////////// +// +// AMaZE demosaic algorithm +// (Aliasing Minimization and Zipper Elimination) +// +// copyright (c) 2008-2010 Emil Martinec +// optimized for speed by Ingo Weyrich +// +// incorporating ideas of Luis Sanz Rodrigues and Paul Lee +// +// code dated: May 27, 2010 +// latest modification: Ingo Weyrich, January 25, 2016 +// +// amaze_interpolate_RT.cc 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. +// +// This program 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 this program. If not, see . +// +//////////////////////////////////////////////////////////////// + +#include "rtengine.h" +#include "rawimagesource.h" +#include "rt_math.h" +#include "sleef.c" +#include "opthelper.h" +#include "jaggedarray.h" +#include "gauss.h" +#include "StopWatch.h" + +using namespace std; +namespace { + +float calcBlendFactor(float val, float threshold) { + // sigmoid function + // result is in ]0;1] range + // inflexion point is at (x, y) (threshold, 0.5) + return 1.f / (1.f + xexpf(16.f - 16.f * val / threshold)); +} + +#ifdef __SSE2__ +vfloat calcBlendFactor(vfloat valv, vfloat thresholdv) { + // sigmoid function + // result is in ]0;1] range + // inflexion point is at (x, y) (threshold, 0.5) + const vfloat onev = F2V(1.f); + const vfloat c16v = F2V(16.f); + return onev / (onev + xexpf(c16v - c16v * valv / thresholdv)); +} +#endif + +void buildBlendMask(float** luminance, rtengine::JaggedArray &blend, int W, int H, float contrastThreshold, float amount = 1.f) { +BENCHFUN + + if(contrastThreshold == 0.f) { + for(int j = 0; j < H; ++j) { + for(int i = 0; i < W; ++i) { + blend[j][i] = 1.f; + } + } + } else { + constexpr float scale = 0.0625f / 327.68f; +#ifdef _OPENMP + #pragma omp parallel +#endif + { +#ifdef __SSE2__ + const vfloat contrastThresholdv = F2V(contrastThreshold); + const vfloat scalev = F2V(scale); + const vfloat amountv = F2V(amount); +#endif +#ifdef _OPENMP + #pragma omp for schedule(dynamic,16) +#endif + + for(int j = 2; j < H - 2; ++j) { + int i = 2; +#ifdef __SSE2__ + for(; i < W - 5; i += 4) { + vfloat contrastv = vsqrtf(SQRV(LVFU(luminance[j][i+1]) - LVFU(luminance[j][i-1])) + SQRV(LVFU(luminance[j+1][i]) - LVFU(luminance[j-1][i])) + + SQRV(LVFU(luminance[j][i+2]) - LVFU(luminance[j][i-2])) + SQRV(LVFU(luminance[j+2][i]) - LVFU(luminance[j-2][i]))) * scalev; + + STVFU(blend[j][i], amountv * calcBlendFactor(contrastv, contrastThresholdv)); + } +#endif + for(; i < W - 2; ++i) { + + float contrast = sqrtf(rtengine::SQR(luminance[j][i+1] - luminance[j][i-1]) + rtengine::SQR(luminance[j+1][i] - luminance[j-1][i]) + + rtengine::SQR(luminance[j][i+2] - luminance[j][i-2]) + rtengine::SQR(luminance[j+2][i] - luminance[j-2][i])) * scale; + + blend[j][i] = amount * calcBlendFactor(contrast, contrastThreshold); + } + } +#ifdef _OPENMP + #pragma omp single +#endif + { + // upper border + for(int j = 0; j < 2; ++j) { + for(int i = 2; i < W - 2; ++i) { + blend[j][i] = blend[2][i]; + } + } + // lower border + for(int j = H - 2; j < H; ++j) { + for(int i = 2; i < W - 2; ++i) { + blend[j][i] = blend[H-3][i]; + } + } + for(int j = 0; j < H; ++j) { + // left border + blend[j][0] = blend[j][1] = blend[j][2]; + // right border + blend[j][W - 2] = blend[j][W - 1] = blend[j][W - 3]; + } + } + // blur blend mask to smooth transitions + gaussianBlur(blend, blend, W, H, 2.0); + } + } +} +} + +namespace rtengine +{ + +void RawImageSource::amaze_vng4_demosaic_RT(int winw, int winh, array2D &rawData, array2D &red, array2D &green, array2D &blue) +{ + BENCHFUN + + vng4_demosaic (); + array2D redTmp(winw, winh); + array2D greenTmp(winw, winh); + array2D blueTmp(winw, winh); + array2D L(winw, winh); + amaze_demosaic_RT (0, 0, winw, winh, rawData, redTmp, greenTmp, blueTmp); + const float xyz_rgb[3][3] = { // XYZ from RGB + { 0.412453, 0.357580, 0.180423 }, + { 0.212671, 0.715160, 0.072169 }, + { 0.019334, 0.119193, 0.950227 } + }; + #pragma omp parallel + { + float a[winw] ALIGNED16; + float b[winw] ALIGNED16; + #pragma omp for + for(int i = 0; i < winh; ++i) { + Color::RGB2Lab(redTmp[i], greenTmp[i], blueTmp[i], L[i], a, b, xyz_rgb, winw); + } + } + // calculate contrast based blend factors to reduce sharpening in regions with low contrast + JaggedArray blend(winw, winh); + buildBlendMask(L, blend, winw, winh, 20.f / 100.f); + #pragma omp parallel for + for(int i = 0; i < winh; ++i) { + for(int j = 0; j < winw; ++j) { + red[i][j] = intp(blend[i][j], redTmp[i][j], red[i][j]); + green[i][j] = intp(blend[i][j], greenTmp[i][j], green[i][j]); + blue[i][j] = intp(blend[i][j], blueTmp[i][j], blue[i][j]); + } + } + +} +} diff --git a/rtengine/rawimagesource.cc b/rtengine/rawimagesource.cc index 6f119a2ad..80c7d8b86 100644 --- a/rtengine/rawimagesource.cc +++ b/rtengine/rawimagesource.cc @@ -2078,7 +2078,8 @@ void RawImageSource::demosaic(const RAWParams &raw) } else if (raw.bayersensor.method == RAWParams::BayerSensor::getMethodString(RAWParams::BayerSensor::Method::DCB) ) { dcb_demosaic(raw.bayersensor.dcb_iterations, raw.bayersensor.dcb_enhance); } else if (raw.bayersensor.method == RAWParams::BayerSensor::getMethodString(RAWParams::BayerSensor::Method::EAHD)) { - eahd_demosaic (); + amaze_vng4_demosaic_RT (W, H, rawData, red, green, blue); +// eahd_demosaic (); } else if (raw.bayersensor.method == RAWParams::BayerSensor::getMethodString(RAWParams::BayerSensor::Method::IGV)) { igv_interpolate(W, H); } else if (raw.bayersensor.method == RAWParams::BayerSensor::getMethodString(RAWParams::BayerSensor::Method::LMMSE)) { diff --git a/rtengine/rawimagesource.h b/rtengine/rawimagesource.h index 0512af790..b188fdd69 100644 --- a/rtengine/rawimagesource.h +++ b/rtengine/rawimagesource.h @@ -268,6 +268,7 @@ protected: void igv_interpolate(int winw, int winh); void lmmse_interpolate_omp(int winw, int winh, array2D &rawData, array2D &red, array2D &green, array2D &blue, int iterations); void amaze_demosaic_RT(int winx, int winy, int winw, int winh, array2D &rawData, array2D &red, array2D &green, array2D &blue);//Emil's code for AMaZE + void amaze_vng4_demosaic_RT(int winw, int winh, array2D &rawData, array2D &red, array2D &green, array2D &blue);//Emil's code for AMaZE void fast_demosaic();//Emil's code for fast demosaicing void dcb_demosaic(int iterations, bool dcb_enhance); void ahd_demosaic(); From 2a13d129368d5fe26d4bd389205743094adf639f Mon Sep 17 00:00:00 2001 From: heckflosse Date: Tue, 29 May 2018 16:59:29 +0200 Subject: [PATCH 06/42] Amaze+VNG4: created own entry in demosaic combobox, cleaned code --- rtdata/languages/default | 1 + rtengine/amaze_vng4_demosaic_RT.cc | 101 +---------------------------- rtengine/color.cc | 39 +++++++++++ rtengine/color.h | 1 + rtengine/ipsharpen.cc | 90 +------------------------ rtengine/procparams.cc | 3 +- rtengine/procparams.h | 3 +- rtengine/rawimagesource.cc | 5 +- rtengine/rt_algo.cc | 93 ++++++++++++++++++++++++++ rtengine/rt_algo.h | 4 +- 10 files changed, 147 insertions(+), 193 deletions(-) diff --git a/rtdata/languages/default b/rtdata/languages/default index 5c0273d3f..02ae8aff1 100644 --- a/rtdata/languages/default +++ b/rtdata/languages/default @@ -1763,6 +1763,7 @@ TP_RAW_1PASSMEDIUM;1-Pass (Medium) TP_RAW_3PASSBEST;3-Pass (Best) TP_RAW_AHD;AHD TP_RAW_AMAZE;AMaZE +TP_RAW_AMAZEVNG4;AMaZE+VNG4 TP_RAW_DCB;DCB TP_RAW_DCBENHANCE;DCB enhancement TP_RAW_DCBITERATIONS;Number of DCB iterations diff --git a/rtengine/amaze_vng4_demosaic_RT.cc b/rtengine/amaze_vng4_demosaic_RT.cc index f6b109bb6..b27c26df0 100644 --- a/rtengine/amaze_vng4_demosaic_RT.cc +++ b/rtengine/amaze_vng4_demosaic_RT.cc @@ -29,104 +29,11 @@ #include "rtengine.h" #include "rawimagesource.h" #include "rt_math.h" -#include "sleef.c" -#include "opthelper.h" -#include "jaggedarray.h" -#include "gauss.h" +#define BENCHMARK #include "StopWatch.h" +#include "rt_algo.h" using namespace std; -namespace { - -float calcBlendFactor(float val, float threshold) { - // sigmoid function - // result is in ]0;1] range - // inflexion point is at (x, y) (threshold, 0.5) - return 1.f / (1.f + xexpf(16.f - 16.f * val / threshold)); -} - -#ifdef __SSE2__ -vfloat calcBlendFactor(vfloat valv, vfloat thresholdv) { - // sigmoid function - // result is in ]0;1] range - // inflexion point is at (x, y) (threshold, 0.5) - const vfloat onev = F2V(1.f); - const vfloat c16v = F2V(16.f); - return onev / (onev + xexpf(c16v - c16v * valv / thresholdv)); -} -#endif - -void buildBlendMask(float** luminance, rtengine::JaggedArray &blend, int W, int H, float contrastThreshold, float amount = 1.f) { -BENCHFUN - - if(contrastThreshold == 0.f) { - for(int j = 0; j < H; ++j) { - for(int i = 0; i < W; ++i) { - blend[j][i] = 1.f; - } - } - } else { - constexpr float scale = 0.0625f / 327.68f; -#ifdef _OPENMP - #pragma omp parallel -#endif - { -#ifdef __SSE2__ - const vfloat contrastThresholdv = F2V(contrastThreshold); - const vfloat scalev = F2V(scale); - const vfloat amountv = F2V(amount); -#endif -#ifdef _OPENMP - #pragma omp for schedule(dynamic,16) -#endif - - for(int j = 2; j < H - 2; ++j) { - int i = 2; -#ifdef __SSE2__ - for(; i < W - 5; i += 4) { - vfloat contrastv = vsqrtf(SQRV(LVFU(luminance[j][i+1]) - LVFU(luminance[j][i-1])) + SQRV(LVFU(luminance[j+1][i]) - LVFU(luminance[j-1][i])) + - SQRV(LVFU(luminance[j][i+2]) - LVFU(luminance[j][i-2])) + SQRV(LVFU(luminance[j+2][i]) - LVFU(luminance[j-2][i]))) * scalev; - - STVFU(blend[j][i], amountv * calcBlendFactor(contrastv, contrastThresholdv)); - } -#endif - for(; i < W - 2; ++i) { - - float contrast = sqrtf(rtengine::SQR(luminance[j][i+1] - luminance[j][i-1]) + rtengine::SQR(luminance[j+1][i] - luminance[j-1][i]) + - rtengine::SQR(luminance[j][i+2] - luminance[j][i-2]) + rtengine::SQR(luminance[j+2][i] - luminance[j-2][i])) * scale; - - blend[j][i] = amount * calcBlendFactor(contrast, contrastThreshold); - } - } -#ifdef _OPENMP - #pragma omp single -#endif - { - // upper border - for(int j = 0; j < 2; ++j) { - for(int i = 2; i < W - 2; ++i) { - blend[j][i] = blend[2][i]; - } - } - // lower border - for(int j = H - 2; j < H; ++j) { - for(int i = 2; i < W - 2; ++i) { - blend[j][i] = blend[H-3][i]; - } - } - for(int j = 0; j < H; ++j) { - // left border - blend[j][0] = blend[j][1] = blend[j][2]; - // right border - blend[j][W - 2] = blend[j][W - 1] = blend[j][W - 3]; - } - } - // blur blend mask to smooth transitions - gaussianBlur(blend, blend, W, H, 2.0); - } - } -} -} namespace rtengine { @@ -148,11 +55,9 @@ void RawImageSource::amaze_vng4_demosaic_RT(int winw, int winh, array2D & }; #pragma omp parallel { - float a[winw] ALIGNED16; - float b[winw] ALIGNED16; #pragma omp for for(int i = 0; i < winh; ++i) { - Color::RGB2Lab(redTmp[i], greenTmp[i], blueTmp[i], L[i], a, b, xyz_rgb, winw); + Color::RGB2L(redTmp[i], greenTmp[i], blueTmp[i], L[i], xyz_rgb, winw); } } // calculate contrast based blend factors to reduce sharpening in regions with low contrast diff --git a/rtengine/color.cc b/rtengine/color.cc index c4e3b6a68..5fb8d27d8 100644 --- a/rtengine/color.cc +++ b/rtengine/color.cc @@ -1837,6 +1837,45 @@ void Color::RGB2Lab(float *R, float *G, float *B, float *L, float *a, float *b, } } +void Color::RGB2L(float *R, float *G, float *B, float *L, const float wp[3][3], int width) +{ + +#ifdef __SSE2__ + vfloat minvalfv = F2V(0.f); + vfloat maxvalfv = F2V(MAXVALF); +#endif + int i = 0; + +#ifdef __SSE2__ + for(;i < width - 3; i+=4) { + const vfloat rv = LVFU(R[i]); + const vfloat gv = LVFU(G[i]); + const vfloat bv = LVFU(B[i]); + const vfloat yv = F2V(wp[1][0]) * rv + F2V(wp[1][1]) * gv + F2V(wp[1][2]) * bv; + + vmask maxMask = vmaskf_gt(yv, maxvalfv); + vmask minMask = vmaskf_lt(yv, minvalfv); + if (_mm_movemask_ps((vfloat)maxMask) || _mm_movemask_ps((vfloat)minMask)) { + // take slower code path for all 4 pixels if one of the values is > MAXVALF. Still faster than non SSE2 version + for(int k = 0; k < 4; ++k) { + float y = yv[k]; + L[i + k] = computeXYZ2LabY(y); + } + } else { + STVFU(L[i], cachefy[yv]); + } + } +#endif + for(;i < width; ++i) { + const float rv = R[i]; + const float gv = G[i]; + const float bv = B[i]; + float y = wp[1][0] * rv + wp[1][1] * gv + wp[1][2] * bv; + + L[i] = computeXYZ2LabY(y); + } +} + void Color::XYZ2Lab(float X, float Y, float Z, float &L, float &a, float &b) { diff --git a/rtengine/color.h b/rtengine/color.h index 5616a4079..3310f6fa6 100644 --- a/rtengine/color.h +++ b/rtengine/color.h @@ -611,6 +611,7 @@ public: */ static void XYZ2Lab(float x, float y, float z, float &L, float &a, float &b); static void RGB2Lab(float *X, float *Y, float *Z, float *L, float *a, float *b, const float wp[3][3], int width); + static void RGB2L(float *X, float *Y, float *Z, float *L, const float wp[3][3], int width); /** * @brief Convert Lab in Yuv diff --git a/rtengine/ipsharpen.cc b/rtengine/ipsharpen.cc index e328edd1b..e3ecf41b3 100644 --- a/rtengine/ipsharpen.cc +++ b/rtengine/ipsharpen.cc @@ -26,99 +26,11 @@ #include "opthelper.h" //#define BENCHMARK #include "StopWatch.h" +#include "rt_algo.h" using namespace std; namespace { -float calcBlendFactor(float val, float threshold) { - // sigmoid function - // result is in ]0;1] range - // inflexion point is at (x, y) (threshold, 0.5) - return 1.f / (1.f + xexpf(16.f - 16.f * val / threshold)); -} - -#ifdef __SSE2__ -vfloat calcBlendFactor(vfloat valv, vfloat thresholdv) { - // sigmoid function - // result is in ]0;1] range - // inflexion point is at (x, y) (threshold, 0.5) - const vfloat onev = F2V(1.f); - const vfloat c16v = F2V(16.f); - return onev / (onev + xexpf(c16v - c16v * valv / thresholdv)); -} -#endif - -void buildBlendMask(float** luminance, rtengine::JaggedArray &blend, int W, int H, float contrastThreshold, float amount = 1.f) { -BENCHFUN - - if(contrastThreshold == 0.f) { - for(int j = 0; j < H; ++j) { - for(int i = 0; i < W; ++i) { - blend[j][i] = 1.f; - } - } - } else { - constexpr float scale = 0.0625f / 327.68f; -#ifdef _OPENMP - #pragma omp parallel -#endif - { -#ifdef __SSE2__ - const vfloat contrastThresholdv = F2V(contrastThreshold); - const vfloat scalev = F2V(scale); - const vfloat amountv = F2V(amount); -#endif -#ifdef _OPENMP - #pragma omp for schedule(dynamic,16) -#endif - - for(int j = 2; j < H - 2; ++j) { - int i = 2; -#ifdef __SSE2__ - for(; i < W - 5; i += 4) { - vfloat contrastv = vsqrtf(SQRV(LVFU(luminance[j][i+1]) - LVFU(luminance[j][i-1])) + SQRV(LVFU(luminance[j+1][i]) - LVFU(luminance[j-1][i])) + - SQRV(LVFU(luminance[j][i+2]) - LVFU(luminance[j][i-2])) + SQRV(LVFU(luminance[j+2][i]) - LVFU(luminance[j-2][i]))) * scalev; - - STVFU(blend[j][i], amountv * calcBlendFactor(contrastv, contrastThresholdv)); - } -#endif - for(; i < W - 2; ++i) { - - float contrast = sqrtf(SQR(luminance[j][i+1] - luminance[j][i-1]) + SQR(luminance[j+1][i] - luminance[j-1][i]) + - SQR(luminance[j][i+2] - luminance[j][i-2]) + SQR(luminance[j+2][i] - luminance[j-2][i])) * scale; - - blend[j][i] = amount * calcBlendFactor(contrast, contrastThreshold); - } - } -#ifdef _OPENMP - #pragma omp single -#endif - { - // upper border - for(int j = 0; j < 2; ++j) { - for(int i = 2; i < W - 2; ++i) { - blend[j][i] = blend[2][i]; - } - } - // lower border - for(int j = H - 2; j < H; ++j) { - for(int i = 2; i < W - 2; ++i) { - blend[j][i] = blend[H-3][i]; - } - } - for(int j = 0; j < H; ++j) { - // left border - blend[j][0] = blend[j][1] = blend[j][2]; - // right border - blend[j][W - 2] = blend[j][W - 1] = blend[j][W - 3]; - } - } - // blur blend mask to smooth transitions - gaussianBlur(blend, blend, W, H, 2.0); - } - } -} - void sharpenHaloCtrl (float** luminance, float** blurmap, float** base, float** blend, int W, int H, const SharpeningParams &sharpenParam) { diff --git a/rtengine/procparams.cc b/rtengine/procparams.cc index dfcb91ebb..ec6df6ace 100644 --- a/rtengine/procparams.cc +++ b/rtengine/procparams.cc @@ -2446,7 +2446,8 @@ const std::vector& RAWParams::BayerSensor::getMethodStrings() "fast", "mono", "none", - "pixelshift" + "pixelshift", + "amazevng4" }; return method_strings; } diff --git a/rtengine/procparams.h b/rtengine/procparams.h index 467ecf1e3..e6a253955 100644 --- a/rtengine/procparams.h +++ b/rtengine/procparams.h @@ -1235,7 +1235,8 @@ struct RAWParams { FAST, MONO, NONE, - PIXELSHIFT + PIXELSHIFT, + AMAZEVNG4 }; enum class PSMotionCorrectionMethod { diff --git a/rtengine/rawimagesource.cc b/rtengine/rawimagesource.cc index 80c7d8b86..9f217e357 100644 --- a/rtengine/rawimagesource.cc +++ b/rtengine/rawimagesource.cc @@ -2073,13 +2073,14 @@ void RawImageSource::demosaic(const RAWParams &raw) ahd_demosaic (); } else if (raw.bayersensor.method == RAWParams::BayerSensor::getMethodString(RAWParams::BayerSensor::Method::AMAZE) ) { amaze_demosaic_RT (0, 0, W, H, rawData, red, green, blue); + } else if (raw.bayersensor.method == RAWParams::BayerSensor::getMethodString(RAWParams::BayerSensor::Method::AMAZEVNG4) ) { + amaze_vng4_demosaic_RT (W, H, rawData, red, green, blue); } else if (raw.bayersensor.method == RAWParams::BayerSensor::getMethodString(RAWParams::BayerSensor::Method::PIXELSHIFT) ) { pixelshift(0, 0, W, H, raw.bayersensor, currFrame, ri->get_maker(), ri->get_model(), raw.expos); } else if (raw.bayersensor.method == RAWParams::BayerSensor::getMethodString(RAWParams::BayerSensor::Method::DCB) ) { dcb_demosaic(raw.bayersensor.dcb_iterations, raw.bayersensor.dcb_enhance); } else if (raw.bayersensor.method == RAWParams::BayerSensor::getMethodString(RAWParams::BayerSensor::Method::EAHD)) { - amaze_vng4_demosaic_RT (W, H, rawData, red, green, blue); -// eahd_demosaic (); + eahd_demosaic (); } else if (raw.bayersensor.method == RAWParams::BayerSensor::getMethodString(RAWParams::BayerSensor::Method::IGV)) { igv_interpolate(W, H); } else if (raw.bayersensor.method == RAWParams::BayerSensor::getMethodString(RAWParams::BayerSensor::Method::LMMSE)) { diff --git a/rtengine/rt_algo.cc b/rtengine/rt_algo.cc index 79508cfb3..21c8eac12 100644 --- a/rtengine/rt_algo.cc +++ b/rtengine/rt_algo.cc @@ -25,7 +25,31 @@ #include #endif +#include "gauss.h" +#include "opthelper.h" #include "rt_algo.h" +#include "rt_math.h" +#include "sleef.c" + +namespace { +float calcBlendFactor(float val, float threshold) { + // sigmoid function + // result is in ]0;1] range + // inflexion point is at (x, y) (threshold, 0.5) + return 1.f / (1.f + xexpf(16.f - 16.f * val / threshold)); +} + +#ifdef __SSE2__ +vfloat calcBlendFactor(vfloat valv, vfloat thresholdv) { + // sigmoid function + // result is in ]0;1] range + // inflexion point is at (x, y) (threshold, 0.5) + const vfloat onev = F2V(1.f); + const vfloat c16v = F2V(16.f); + return onev / (onev + xexpf(c16v - c16v * valv / thresholdv)); +} +#endif +} namespace rtengine { @@ -164,4 +188,73 @@ void findMinMaxPercentile(const float* data, size_t size, float minPrct, float& maxOut += minVal; } +void buildBlendMask(float** luminance, rtengine::JaggedArray &blend, int W, int H, float contrastThreshold, float amount) { + + if(contrastThreshold == 0.f) { + for(int j = 0; j < H; ++j) { + for(int i = 0; i < W; ++i) { + blend[j][i] = 1.f; + } + } + } else { + constexpr float scale = 0.0625f / 327.68f; +#ifdef _OPENMP + #pragma omp parallel +#endif + { +#ifdef __SSE2__ + const vfloat contrastThresholdv = F2V(contrastThreshold); + const vfloat scalev = F2V(scale); + const vfloat amountv = F2V(amount); +#endif +#ifdef _OPENMP + #pragma omp for schedule(dynamic,16) +#endif + + for(int j = 2; j < H - 2; ++j) { + int i = 2; +#ifdef __SSE2__ + for(; i < W - 5; i += 4) { + vfloat contrastv = vsqrtf(SQRV(LVFU(luminance[j][i+1]) - LVFU(luminance[j][i-1])) + SQRV(LVFU(luminance[j+1][i]) - LVFU(luminance[j-1][i])) + + SQRV(LVFU(luminance[j][i+2]) - LVFU(luminance[j][i-2])) + SQRV(LVFU(luminance[j+2][i]) - LVFU(luminance[j-2][i]))) * scalev; + + STVFU(blend[j][i], amountv * calcBlendFactor(contrastv, contrastThresholdv)); + } +#endif + for(; i < W - 2; ++i) { + + float contrast = sqrtf(rtengine::SQR(luminance[j][i+1] - luminance[j][i-1]) + rtengine::SQR(luminance[j+1][i] - luminance[j-1][i]) + + rtengine::SQR(luminance[j][i+2] - luminance[j][i-2]) + rtengine::SQR(luminance[j+2][i] - luminance[j-2][i])) * scale; + + blend[j][i] = amount * calcBlendFactor(contrast, contrastThreshold); + } + } +#ifdef _OPENMP + #pragma omp single +#endif + { + // upper border + for(int j = 0; j < 2; ++j) { + for(int i = 2; i < W - 2; ++i) { + blend[j][i] = blend[2][i]; + } + } + // lower border + for(int j = H - 2; j < H; ++j) { + for(int i = 2; i < W - 2; ++i) { + blend[j][i] = blend[H-3][i]; + } + } + for(int j = 0; j < H; ++j) { + // left border + blend[j][0] = blend[j][1] = blend[j][2]; + // right border + blend[j][W - 2] = blend[j][W - 1] = blend[j][W - 3]; + } + } + // blur blend mask to smooth transitions + gaussianBlur(blend, blend, W, H, 2.0); + } + } +} } diff --git a/rtengine/rt_algo.h b/rtengine/rt_algo.h index 2630bbf41..1aac26c3e 100644 --- a/rtengine/rt_algo.h +++ b/rtengine/rt_algo.h @@ -20,10 +20,10 @@ #pragma once #include +#include "jaggedarray.h" namespace rtengine { - void findMinMaxPercentile(const float* data, size_t size, float minPrct, float& minOut, float maxPrct, float& maxOut, bool multiThread = true); - +void buildBlendMask(float** luminance, rtengine::JaggedArray &blend, int W, int H, float contrastThreshold, float amount = 1.f); } From 355fcbad8e126f01ee976611b5dd0d412a64994e Mon Sep 17 00:00:00 2001 From: heckflosse Date: Wed, 30 May 2018 14:39:29 +0200 Subject: [PATCH 07/42] AMaZE+VNG4: added contrast threshold adjuster, #4579 --- rtdata/languages/default | 2 + rtengine/amaze_vng4_demosaic_RT.cc | 91 +++++++++++++++++------------- rtengine/color.cc | 2 +- rtengine/procparams.cc | 5 ++ rtengine/procparams.h | 1 + rtengine/rawimagesource.cc | 2 +- rtengine/rawimagesource.h | 2 +- rtgui/bayerprocess.cc | 41 ++++++++++++++ rtgui/bayerprocess.h | 3 + rtgui/paramsedited.cc | 8 ++- rtgui/paramsedited.h | 1 + 11 files changed, 116 insertions(+), 42 deletions(-) diff --git a/rtdata/languages/default b/rtdata/languages/default index 02ae8aff1..5f16404c2 100644 --- a/rtdata/languages/default +++ b/rtdata/languages/default @@ -727,6 +727,7 @@ HISTORY_MSG_492;RGB Curves HISTORY_MSG_493;L*a*b* Adjustments HISTORY_MSG_CLAMPOOG;Out-of-gamut color clipping HISTORY_MSG_COLORTONING_LABGRID_VALUE;CT - Color correction +HISTORY_MSG_DUALDEMOSAIC_CONTRAST;AMaZE+VNG4 - Contrast threshold HISTORY_MSG_HISTMATCHING;Auto-Matched Tone Curve HISTORY_MSG_LOCALCONTRAST_AMOUNT;Local Contrast - Amount HISTORY_MSG_LOCALCONTRAST_DARKNESS;Local Contrast - Darkness @@ -1771,6 +1772,7 @@ TP_RAW_DMETHOD;Method TP_RAW_DMETHOD_PROGRESSBAR;%1 demosaicing... TP_RAW_DMETHOD_PROGRESSBAR_REFINE;Demosaicing refinement... TP_RAW_DMETHOD_TOOLTIP;Note: IGV and LMMSE are dedicated to high ISO images to aid in noise reduction without leading to maze patterns, posterization or a washed-out look.\nPixel Shift is for Pentax/Sony Pixel Shift files. It falls back to AMaZE for non-Pixel Shift files. +TP_RAW_DUALDEMOSAICCONTRAST;Contrast threshold TP_RAW_EAHD;EAHD TP_RAW_FALSECOLOR;False color suppression steps TP_RAW_FAST;Fast diff --git a/rtengine/amaze_vng4_demosaic_RT.cc b/rtengine/amaze_vng4_demosaic_RT.cc index b27c26df0..0dae2c49b 100644 --- a/rtengine/amaze_vng4_demosaic_RT.cc +++ b/rtengine/amaze_vng4_demosaic_RT.cc @@ -1,17 +1,14 @@ //////////////////////////////////////////////////////////////// // -// AMaZE demosaic algorithm -// (Aliasing Minimization and Zipper Elimination) +// combined AMaZE + VNG4 demosaic algorithm // -// copyright (c) 2008-2010 Emil Martinec -// optimized for speed by Ingo Weyrich // -// incorporating ideas of Luis Sanz Rodrigues and Paul Lee +// copyright (c) 2018 Ingo Weyrich // -// code dated: May 27, 2010 -// latest modification: Ingo Weyrich, January 25, 2016 +// blends AMaZE and VNG4 output based on contrast // -// amaze_interpolate_RT.cc is free software: you can redistribute it and/or modify +// +// amaze_vng4_demosaic_RT.cc 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. @@ -38,39 +35,57 @@ using namespace std; namespace rtengine { -void RawImageSource::amaze_vng4_demosaic_RT(int winw, int winh, array2D &rawData, array2D &red, array2D &green, array2D &blue) +void RawImageSource::amaze_vng4_demosaic_RT(int winw, int winh, array2D &rawData, array2D &red, array2D &green, array2D &blue, double contrast) { BENCHFUN - vng4_demosaic (); - array2D redTmp(winw, winh); - array2D greenTmp(winw, winh); - array2D blueTmp(winw, winh); - array2D L(winw, winh); - amaze_demosaic_RT (0, 0, winw, winh, rawData, redTmp, greenTmp, blueTmp); - const float xyz_rgb[3][3] = { // XYZ from RGB - { 0.412453, 0.357580, 0.180423 }, - { 0.212671, 0.715160, 0.072169 }, - { 0.019334, 0.119193, 0.950227 } - }; - #pragma omp parallel - { - #pragma omp for - for(int i = 0; i < winh; ++i) { - Color::RGB2L(redTmp[i], greenTmp[i], blueTmp[i], L[i], xyz_rgb, winw); - } - } - // calculate contrast based blend factors to reduce sharpening in regions with low contrast - JaggedArray blend(winw, winh); - buildBlendMask(L, blend, winw, winh, 20.f / 100.f); - #pragma omp parallel for - for(int i = 0; i < winh; ++i) { - for(int j = 0; j < winw; ++j) { - red[i][j] = intp(blend[i][j], redTmp[i][j], red[i][j]); - green[i][j] = intp(blend[i][j], greenTmp[i][j], green[i][j]); - blue[i][j] = intp(blend[i][j], blueTmp[i][j], blue[i][j]); - } - } + if (contrast == 0.0) { + // contrast == 0.0 means only AMaZE will be used + amaze_demosaic_RT (0, 0, winw, winh, rawData, red, green, blue); + return; + } + + vng4_demosaic (); + array2D redTmp(winw, winh); + array2D greenTmp(winw, winh); + array2D blueTmp(winw, winh); + array2D L(winw, winh); + amaze_demosaic_RT (0, 0, winw, winh, rawData, redTmp, greenTmp, blueTmp); + const float xyz_rgb[3][3] = { // XYZ from RGB + { 0.412453, 0.357580, 0.180423 }, + { 0.212671, 0.715160, 0.072169 }, + { 0.019334, 0.119193, 0.950227 } + }; + #pragma omp parallel + { + #pragma omp for + for(int i = 0; i < winh; ++i) { + Color::RGB2L(redTmp[i], greenTmp[i], blueTmp[i], L[i], xyz_rgb, winw); + } + } + // calculate contrast based blend factors to reduce sharpening in regions with low contrast + JaggedArray blend(winw, winh); + buildBlendMask(L, blend, winw, winh, contrast / 100.f); + + // the following is split into 3 loops intentionally to avoid cache conflicts on CPUs with only 4-way cache + #pragma omp parallel for + for(int i = 0; i < winh; ++i) { + for(int j = 0; j < winw; ++j) { + red[i][j] = intp(blend[i][j], redTmp[i][j], red[i][j]); + } + } + #pragma omp parallel for + for(int i = 0; i < winh; ++i) { + for(int j = 0; j < winw; ++j) { + green[i][j] = intp(blend[i][j], greenTmp[i][j], green[i][j]); + } + } + #pragma omp parallel for + for(int i = 0; i < winh; ++i) { + for(int j = 0; j < winw; ++j) { + blue[i][j] = intp(blend[i][j], blueTmp[i][j], blue[i][j]); + } + } } } diff --git a/rtengine/color.cc b/rtengine/color.cc index 5fb8d27d8..3cedcaaa6 100644 --- a/rtengine/color.cc +++ b/rtengine/color.cc @@ -1855,7 +1855,7 @@ void Color::RGB2L(float *R, float *G, float *B, float *L, const float wp[3][3], vmask maxMask = vmaskf_gt(yv, maxvalfv); vmask minMask = vmaskf_lt(yv, minvalfv); - if (_mm_movemask_ps((vfloat)maxMask) || _mm_movemask_ps((vfloat)minMask)) { + if (_mm_movemask_ps((vfloat)vorm(maxMask, minMask))) { // take slower code path for all 4 pixels if one of the values is > MAXVALF. Still faster than non SSE2 version for(int k = 0; k < 4; ++k) { float y = yv[k]; diff --git a/rtengine/procparams.cc b/rtengine/procparams.cc index ec6df6ace..eb47d29db 100644 --- a/rtengine/procparams.cc +++ b/rtengine/procparams.cc @@ -2357,6 +2357,7 @@ RAWParams::BayerSensor::BayerSensor() : greenthresh(0), dcb_iterations(2), lmmse_iterations(2), + dualDemosaicContrast(20), pixelShiftMotionCorrectionMethod(PSMotionCorrectionMethod::AUTO), pixelShiftEperIso(0.0), pixelShiftSigma(1.0), @@ -2392,6 +2393,7 @@ bool RAWParams::BayerSensor::operator ==(const BayerSensor& other) const && greenthresh == other.greenthresh && dcb_iterations == other.dcb_iterations && lmmse_iterations == other.lmmse_iterations + && dualDemosaicContrast == other.dualDemosaicContrast && pixelShiftMotionCorrectionMethod == other.pixelShiftMotionCorrectionMethod && pixelShiftEperIso == other.pixelShiftEperIso && pixelShiftSigma == other.pixelShiftSigma @@ -3333,6 +3335,7 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo saveToKeyfile(!pedited || pedited->raw.bayersensor.dcbIterations, "RAW Bayer", "DCBIterations", raw.bayersensor.dcb_iterations, keyFile); saveToKeyfile(!pedited || pedited->raw.bayersensor.dcbEnhance, "RAW Bayer", "DCBEnhance", raw.bayersensor.dcb_enhance, keyFile); saveToKeyfile(!pedited || pedited->raw.bayersensor.lmmseIterations, "RAW Bayer", "LMMSEIterations", raw.bayersensor.lmmse_iterations, keyFile); + saveToKeyfile(!pedited || pedited->raw.bayersensor.dualDemosaicContrast, "RAW Bayer", "DualDemosaicContrast", raw.bayersensor.dualDemosaicContrast, keyFile); saveToKeyfile(!pedited || pedited->raw.bayersensor.pixelShiftMotionCorrectionMethod, "RAW Bayer", "PixelShiftMotionCorrectionMethod", toUnderlying(raw.bayersensor.pixelShiftMotionCorrectionMethod), keyFile); saveToKeyfile(!pedited || pedited->raw.bayersensor.pixelShiftEperIso, "RAW Bayer", "PixelShiftEperIso", raw.bayersensor.pixelShiftEperIso, keyFile); saveToKeyfile(!pedited || pedited->raw.bayersensor.pixelShiftSigma, "RAW Bayer", "PixelShiftSigma", raw.bayersensor.pixelShiftSigma, keyFile); @@ -4622,6 +4625,7 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited) assignFromKeyfile(keyFile, "RAW", "DCBIterations", pedited, raw.bayersensor.dcb_iterations, pedited->raw.bayersensor.dcbIterations); assignFromKeyfile(keyFile, "RAW", "DCBEnhance", pedited, raw.bayersensor.dcb_enhance, pedited->raw.bayersensor.dcbEnhance); assignFromKeyfile(keyFile, "RAW", "LMMSEIterations", pedited, raw.bayersensor.lmmse_iterations, pedited->raw.bayersensor.lmmseIterations); + assignFromKeyfile(keyFile, "RAW", "DualDemosaicContrast", pedited, raw.bayersensor.dualDemosaicContrast, pedited->raw.bayersensor.dualDemosaicContrast); assignFromKeyfile(keyFile, "RAW", "PreBlackzero", pedited, raw.bayersensor.black0, pedited->raw.bayersensor.exBlack0); assignFromKeyfile(keyFile, "RAW", "PreBlackone", pedited, raw.bayersensor.black1, pedited->raw.bayersensor.exBlack1); assignFromKeyfile(keyFile, "RAW", "PreBlacktwo", pedited, raw.bayersensor.black2, pedited->raw.bayersensor.exBlack2); @@ -4658,6 +4662,7 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited) assignFromKeyfile(keyFile, "RAW Bayer", "DCBIterations", pedited, raw.bayersensor.dcb_iterations, pedited->raw.bayersensor.dcbIterations); assignFromKeyfile(keyFile, "RAW Bayer", "DCBEnhance", pedited, raw.bayersensor.dcb_enhance, pedited->raw.bayersensor.dcbEnhance); assignFromKeyfile(keyFile, "RAW Bayer", "LMMSEIterations", pedited, raw.bayersensor.lmmse_iterations, pedited->raw.bayersensor.lmmseIterations); + assignFromKeyfile(keyFile, "RAW Bayer", "DualDemosaicContrast", pedited, raw.bayersensor.dualDemosaicContrast, pedited->raw.bayersensor.dualDemosaicContrast); if (keyFile.has_key ("RAW Bayer", "PixelShiftMotionCorrectionMethod")) { raw.bayersensor.pixelShiftMotionCorrectionMethod = (RAWParams::BayerSensor::PSMotionCorrectionMethod)keyFile.get_integer ("RAW Bayer", "PixelShiftMotionCorrectionMethod"); diff --git a/rtengine/procparams.h b/rtengine/procparams.h index e6a253955..be7784e1b 100644 --- a/rtengine/procparams.h +++ b/rtengine/procparams.h @@ -1264,6 +1264,7 @@ struct RAWParams { int greenthresh; int dcb_iterations; int lmmse_iterations; + double dualDemosaicContrast; PSMotionCorrectionMethod pixelShiftMotionCorrectionMethod; double pixelShiftEperIso; double pixelShiftSigma; diff --git a/rtengine/rawimagesource.cc b/rtengine/rawimagesource.cc index 9f217e357..ce300bcd7 100644 --- a/rtengine/rawimagesource.cc +++ b/rtengine/rawimagesource.cc @@ -2074,7 +2074,7 @@ void RawImageSource::demosaic(const RAWParams &raw) } else if (raw.bayersensor.method == RAWParams::BayerSensor::getMethodString(RAWParams::BayerSensor::Method::AMAZE) ) { amaze_demosaic_RT (0, 0, W, H, rawData, red, green, blue); } else if (raw.bayersensor.method == RAWParams::BayerSensor::getMethodString(RAWParams::BayerSensor::Method::AMAZEVNG4) ) { - amaze_vng4_demosaic_RT (W, H, rawData, red, green, blue); + amaze_vng4_demosaic_RT (W, H, rawData, red, green, blue, raw.bayersensor.dualDemosaicContrast); } else if (raw.bayersensor.method == RAWParams::BayerSensor::getMethodString(RAWParams::BayerSensor::Method::PIXELSHIFT) ) { pixelshift(0, 0, W, H, raw.bayersensor, currFrame, ri->get_maker(), ri->get_model(), raw.expos); } else if (raw.bayersensor.method == RAWParams::BayerSensor::getMethodString(RAWParams::BayerSensor::Method::DCB) ) { diff --git a/rtengine/rawimagesource.h b/rtengine/rawimagesource.h index b188fdd69..e2467dba6 100644 --- a/rtengine/rawimagesource.h +++ b/rtengine/rawimagesource.h @@ -268,7 +268,7 @@ protected: void igv_interpolate(int winw, int winh); void lmmse_interpolate_omp(int winw, int winh, array2D &rawData, array2D &red, array2D &green, array2D &blue, int iterations); void amaze_demosaic_RT(int winx, int winy, int winw, int winh, array2D &rawData, array2D &red, array2D &green, array2D &blue);//Emil's code for AMaZE - void amaze_vng4_demosaic_RT(int winw, int winh, array2D &rawData, array2D &red, array2D &green, array2D &blue);//Emil's code for AMaZE + void amaze_vng4_demosaic_RT(int winw, int winh, array2D &rawData, array2D &red, array2D &green, array2D &blue, double contrast = 0.0); void fast_demosaic();//Emil's code for fast demosaicing void dcb_demosaic(int iterations, bool dcb_enhance); void ahd_demosaic(); diff --git a/rtgui/bayerprocess.cc b/rtgui/bayerprocess.cc index 73fea1aa3..d08ec0393 100644 --- a/rtgui/bayerprocess.cc +++ b/rtgui/bayerprocess.cc @@ -17,6 +17,7 @@ * along with RawTherapee. If not, see . */ #include "bayerprocess.h" +#include "eventmapper.h" #include "options.h" #include "guiutils.h" using namespace rtengine; @@ -25,6 +26,10 @@ using namespace rtengine::procparams; BayerProcess::BayerProcess () : FoldableToolPanel(this, "bayerprocess", M("TP_RAW_LABEL"), true) { + + auto m = ProcEventMapper::getInstance(); + EvDemosaicContrast = m->newEvent(DEMOSAIC, "HISTORY_MSG_DUALDEMOSAIC_CONTRAST"); + Gtk::HBox* hb1 = Gtk::manage (new Gtk::HBox ()); hb1->pack_start (*Gtk::manage (new Gtk::Label ( M("TP_RAW_DMETHOD") + ": ")), Gtk::PACK_SHRINK, 4); method = Gtk::manage (new MyComboBoxText ()); @@ -93,6 +98,20 @@ BayerProcess::BayerProcess () : FoldableToolPanel(this, "bayerprocess", M("TP_RA lmmseOptions->pack_start(*lmmseIterations); pack_start( *lmmseOptions, Gtk::PACK_SHRINK, 4); + dualDemosaicOptions = Gtk::manage (new Gtk::VBox ()); + + dualDemosaicContrast = Gtk::manage(new Adjuster (M("TP_RAW_DUALDEMOSAICCONTRAST"), 0, 200, 1, 20)); + dualDemosaicContrast->setAdjusterListener (this); +// dualDemosaicContrast->set_tooltip_markup (M("TP_RAW_LMMSE_TOOLTIP")); + + if (dualDemosaicContrast->delay < options.adjusterMaxDelay) { + dualDemosaicContrast->delay = options.adjusterMaxDelay; + } + + dualDemosaicContrast->show(); + dualDemosaicOptions->pack_start(*dualDemosaicContrast); + pack_start( *dualDemosaicOptions, Gtk::PACK_SHRINK, 4); + pixelShiftFrame = Gtk::manage (new Gtk::VBox ()); pixelShiftFrame->set_border_width(0); @@ -248,6 +267,7 @@ void BayerProcess::read(const rtengine::procparams::ProcParams* pp, const Params pixelShiftNonGreenCross->setValue (pp->raw.bayersensor.pixelShiftNonGreenCross); ccSteps->setValue (pp->raw.bayersensor.ccSteps); lmmseIterations->setValue (pp->raw.bayersensor.lmmse_iterations); + dualDemosaicContrast->setValue (pp->raw.bayersensor.dualDemosaicContrast); pixelShiftMotionMethod->set_active ((int)pp->raw.bayersensor.pixelShiftMotionCorrectionMethod); pixelShiftEperIso->setValue (pp->raw.bayersensor.pixelShiftEperIso); pixelShiftSigma->setValue (pp->raw.bayersensor.pixelShiftSigma); @@ -271,6 +291,7 @@ void BayerProcess::read(const rtengine::procparams::ProcParams* pp, const Params pixelShiftEqualBrightChannel->setEdited (pedited->raw.bayersensor.pixelShiftEqualBrightChannel); pixelShiftNonGreenCross->setEdited (pedited->raw.bayersensor.pixelShiftNonGreenCross); lmmseIterations->setEditedState ( pedited->raw.bayersensor.lmmseIterations ? Edited : UnEdited); + dualDemosaicContrast->setEditedState ( pedited->raw.bayersensor.dualDemosaicContrast ? Edited : UnEdited); pixelShiftEperIso->setEditedState ( pedited->raw.bayersensor.pixelShiftEperIso ? Edited : UnEdited); pixelShiftSigma->setEditedState ( pedited->raw.bayersensor.pixelShiftSigma ? Edited : UnEdited); @@ -298,6 +319,12 @@ void BayerProcess::read(const rtengine::procparams::ProcParams* pp, const Params } else { lmmseOptions->hide(); } + if (pp->raw.bayersensor.method == procparams::RAWParams::BayerSensor::getMethodString(procparams::RAWParams::BayerSensor::Method::AMAZEVNG4) || + method->get_active_row_number() == std::numeric_limits::max()) { + dualDemosaicOptions->show(); + } else { + dualDemosaicOptions->hide(); + } if (pp->raw.bayersensor.method == procparams::RAWParams::BayerSensor::getMethodString(procparams::RAWParams::BayerSensor::Method::PIXELSHIFT) || method->get_active_row_number() == std::numeric_limits::max()) { if(pp->raw.bayersensor.pixelShiftMotionCorrectionMethod == RAWParams::BayerSensor::PSMotionCorrectionMethod::CUSTOM) { @@ -335,6 +362,7 @@ void BayerProcess::write( rtengine::procparams::ProcParams* pp, ParamsEdited* pe pp->raw.bayersensor.dcb_enhance = dcbEnhance->getLastActive (); //pp->raw.bayersensor.all_enhance = allEnhance->getLastActive (); pp->raw.bayersensor.lmmse_iterations = lmmseIterations->getIntValue(); + pp->raw.bayersensor.dualDemosaicContrast = dualDemosaicContrast->getValue(); pp->raw.bayersensor.pixelShiftMotionCorrectionMethod = (RAWParams::BayerSensor::PSMotionCorrectionMethod)pixelShiftMotionMethod->get_active_row_number(); pp->raw.bayersensor.pixelShiftEperIso = pixelShiftEperIso->getValue(); pp->raw.bayersensor.pixelShiftSigma = pixelShiftSigma->getValue(); @@ -369,6 +397,7 @@ void BayerProcess::write( rtengine::procparams::ProcParams* pp, ParamsEdited* pe pedited->raw.bayersensor.dcbEnhance = !dcbEnhance->get_inconsistent(); //pedited->raw.bayersensor.allEnhance = !allEnhance->get_inconsistent(); pedited->raw.bayersensor.lmmseIterations = lmmseIterations->getEditedState (); + pedited->raw.bayersensor.dualDemosaicContrast = dualDemosaicContrast->getEditedState (); pedited->raw.bayersensor.pixelShiftMotionCorrectionMethod = pixelShiftMotionMethod->get_active_text() != M("GENERAL_UNCHANGED"); pedited->raw.bayersensor.pixelShiftEperIso = pixelShiftEperIso->getEditedState (); pedited->raw.bayersensor.pixelShiftSigma = pixelShiftSigma->getEditedState (); @@ -398,6 +427,7 @@ void BayerProcess::setBatchMode(bool batchMode) ccSteps->showEditedCB (); dcbIterations->showEditedCB (); lmmseIterations->showEditedCB (); + dualDemosaicContrast->showEditedCB (); pixelShiftEperIso->showEditedCB (); pixelShiftSigma->showEditedCB (); } @@ -406,6 +436,7 @@ void BayerProcess::setDefaults(const rtengine::procparams::ProcParams* defParams { dcbIterations->setDefault( defParams->raw.bayersensor.dcb_iterations); lmmseIterations->setDefault( defParams->raw.bayersensor.lmmse_iterations); + dualDemosaicContrast->setDefault( defParams->raw.bayersensor.dualDemosaicContrast); pixelShiftEperIso->setDefault( defParams->raw.bayersensor.pixelShiftEperIso); pixelShiftSigma->setDefault( defParams->raw.bayersensor.pixelShiftSigma); ccSteps->setDefault (defParams->raw.bayersensor.ccSteps); @@ -413,12 +444,14 @@ void BayerProcess::setDefaults(const rtengine::procparams::ProcParams* defParams if (pedited) { dcbIterations->setDefaultEditedState( pedited->raw.bayersensor.dcbIterations ? Edited : UnEdited); lmmseIterations->setDefaultEditedState( pedited->raw.bayersensor.lmmseIterations ? Edited : UnEdited); + dualDemosaicContrast->setDefaultEditedState( pedited->raw.bayersensor.dualDemosaicContrast ? Edited : UnEdited); pixelShiftEperIso->setDefaultEditedState( pedited->raw.bayersensor.pixelShiftEperIso ? Edited : UnEdited); pixelShiftSigma->setDefaultEditedState( pedited->raw.bayersensor.pixelShiftSigma ? Edited : UnEdited); ccSteps->setDefaultEditedState(pedited->raw.bayersensor.ccSteps ? Edited : UnEdited); } else { dcbIterations->setDefaultEditedState( Irrelevant ); lmmseIterations->setDefaultEditedState( Irrelevant ); + dualDemosaicContrast->setDefaultEditedState( Irrelevant ); pixelShiftEperIso->setDefaultEditedState( Irrelevant ); pixelShiftSigma->setDefaultEditedState( Irrelevant ); ccSteps->setDefaultEditedState(Irrelevant ); @@ -434,6 +467,8 @@ void BayerProcess::adjusterChanged (Adjuster* a, double newval) listener->panelChanged (EvDemosaicFalseColorIter, a->getTextValue() ); } else if (a == lmmseIterations) { listener->panelChanged (EvDemosaicLMMSEIter, a->getTextValue() ); + } else if (a == dualDemosaicContrast) { + listener->panelChanged (EvDemosaicContrast, a->getTextValue() ); } else if (a == pixelShiftEperIso) { listener->panelChanged (EvPixelShiftEperIso, a->getTextValue() ); } else if (a == pixelShiftSigma) { @@ -462,6 +497,12 @@ void BayerProcess::methodChanged () lmmseOptions->hide(); } + if (method == procparams::RAWParams::BayerSensor::Method::AMAZEVNG4) { + dualDemosaicOptions->show(); + } else { + dualDemosaicOptions->hide(); + } + if (method == procparams::RAWParams::BayerSensor::Method::PIXELSHIFT) { if(pixelShiftMotionMethod->get_active_row_number() == 2) { pixelShiftOptions->show(); diff --git a/rtgui/bayerprocess.h b/rtgui/bayerprocess.h index 48b445d90..84701a52e 100644 --- a/rtgui/bayerprocess.h +++ b/rtgui/bayerprocess.h @@ -55,9 +55,12 @@ protected: Adjuster* pixelShiftSmooth; Adjuster* pixelShiftEperIso; Adjuster* pixelShiftSigma; + Gtk::VBox *dualDemosaicOptions; + Adjuster* dualDemosaicContrast; int oldMethod; IdleRegister idle_register; + rtengine::ProcEvent EvDemosaicContrast; public: BayerProcess (); diff --git a/rtgui/paramsedited.cc b/rtgui/paramsedited.cc index 0eebe2e41..bf5a63fa8 100644 --- a/rtgui/paramsedited.cc +++ b/rtgui/paramsedited.cc @@ -403,6 +403,7 @@ void ParamsEdited::set (bool v) raw.bayersensor.dcbEnhance = v; //raw.bayersensor.allEnhance = v; raw.bayersensor.lmmseIterations = v; + raw.bayersensor.dualDemosaicContrast = v; raw.bayersensor.pixelShiftMotionCorrectionMethod = v; raw.bayersensor.pixelShiftEperIso = v; raw.bayersensor.pixelShiftSigma = v; @@ -952,6 +953,7 @@ void ParamsEdited::initFrom (const std::vector raw.bayersensor.dcbEnhance = raw.bayersensor.dcbEnhance && p.raw.bayersensor.dcb_enhance == other.raw.bayersensor.dcb_enhance; //raw.bayersensor.allEnhance = raw.bayersensor.allEnhance && p.raw.bayersensor.all_enhance == other.raw.bayersensor.all_enhance; raw.bayersensor.lmmseIterations = raw.bayersensor.lmmseIterations && p.raw.bayersensor.lmmse_iterations == other.raw.bayersensor.lmmse_iterations; + raw.bayersensor.dualDemosaicContrast = raw.bayersensor.dualDemosaicContrast && p.raw.bayersensor.dualDemosaicContrast == other.raw.bayersensor.dualDemosaicContrast; raw.bayersensor.pixelShiftMotionCorrectionMethod = raw.bayersensor.pixelShiftMotionCorrectionMethod && p.raw.bayersensor.pixelShiftMotionCorrectionMethod == other.raw.bayersensor.pixelShiftMotionCorrectionMethod; raw.bayersensor.pixelShiftEperIso = raw.bayersensor.pixelShiftEperIso && p.raw.bayersensor.pixelShiftEperIso == other.raw.bayersensor.pixelShiftEperIso; raw.bayersensor.pixelShiftSigma = raw.bayersensor.pixelShiftSigma && p.raw.bayersensor.pixelShiftSigma == other.raw.bayersensor.pixelShiftSigma; @@ -2496,6 +2498,10 @@ void ParamsEdited::combine (rtengine::procparams::ProcParams& toEdit, const rten toEdit.raw.bayersensor.lmmse_iterations = mods.raw.bayersensor.lmmse_iterations; } + if (raw.bayersensor.dualDemosaicContrast) { + toEdit.raw.bayersensor.dualDemosaicContrast = mods.raw.bayersensor.dualDemosaicContrast; + } + if (raw.bayersensor.pixelShiftMotionCorrectionMethod) { toEdit.raw.bayersensor.pixelShiftMotionCorrectionMethod = mods.raw.bayersensor.pixelShiftMotionCorrectionMethod; } @@ -3072,7 +3078,7 @@ void ParamsEdited::combine (rtengine::procparams::ProcParams& toEdit, const rten bool RAWParamsEdited::BayerSensor::isUnchanged() const { - return method && imageNum && dcbIterations && dcbEnhance && lmmseIterations/*&& allEnhance*/ && greenEq + return method && imageNum && dcbIterations && dcbEnhance && lmmseIterations && dualDemosaicContrast /*&& allEnhance*/ && greenEq && pixelShiftMotionCorrectionMethod && pixelShiftEperIso && pixelShiftSigma && pixelShiftShowMotion && pixelShiftShowMotionMaskOnly && pixelShiftHoleFill && pixelShiftMedian && pixelShiftNonGreenCross && pixelShiftGreen && pixelShiftBlur && pixelShiftSmooth && pixelShiftLmmse && pixelShiftEqualBright && pixelShiftEqualBrightChannel && linenoise && linenoiseDirection && pdafLinesFilter && exBlack0 && exBlack1 && exBlack2 && exBlack3 && exTwoGreen; diff --git a/rtgui/paramsedited.h b/rtgui/paramsedited.h index 47fb70ef0..5b3370b9a 100644 --- a/rtgui/paramsedited.h +++ b/rtgui/paramsedited.h @@ -731,6 +731,7 @@ public: bool dcbIterations; bool dcbEnhance; bool lmmseIterations; + bool dualDemosaicContrast; bool pixelShiftMotionCorrectionMethod; bool pixelShiftEperIso; bool pixelShiftSigma; From a0b8626b7d5e5014bf94603ae0885216647f42a6 Mon Sep 17 00:00:00 2001 From: Hombre Date: Thu, 31 May 2018 00:44:16 +0200 Subject: [PATCH 08/42] Adding ADD/SET mechanism to the raw processing tools see #4579 --- rtengine/procparams.cc | 2 -- rtgui/addsetids.h | 7 +++++ rtgui/batchtoolpanelcoord.cc | 11 ++++++++ rtgui/bayerprocess.cc | 52 +++++++++++++++++++----------------- rtgui/bayerprocess.h | 18 +++++++------ rtgui/ppversion.h | 4 ++- rtgui/preferences.cc | 13 +++++++++ rtgui/xtransprocess.cc | 5 ++++ rtgui/xtransprocess.h | 13 ++++----- 9 files changed, 83 insertions(+), 42 deletions(-) diff --git a/rtengine/procparams.cc b/rtengine/procparams.cc index eb47d29db..3a244f5e8 100644 --- a/rtengine/procparams.cc +++ b/rtengine/procparams.cc @@ -33,7 +33,6 @@ #include "../rtgui/version.h" using namespace std; -extern Options options; namespace { @@ -4625,7 +4624,6 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited) assignFromKeyfile(keyFile, "RAW", "DCBIterations", pedited, raw.bayersensor.dcb_iterations, pedited->raw.bayersensor.dcbIterations); assignFromKeyfile(keyFile, "RAW", "DCBEnhance", pedited, raw.bayersensor.dcb_enhance, pedited->raw.bayersensor.dcbEnhance); assignFromKeyfile(keyFile, "RAW", "LMMSEIterations", pedited, raw.bayersensor.lmmse_iterations, pedited->raw.bayersensor.lmmseIterations); - assignFromKeyfile(keyFile, "RAW", "DualDemosaicContrast", pedited, raw.bayersensor.dualDemosaicContrast, pedited->raw.bayersensor.dualDemosaicContrast); assignFromKeyfile(keyFile, "RAW", "PreBlackzero", pedited, raw.bayersensor.black0, pedited->raw.bayersensor.exBlack0); assignFromKeyfile(keyFile, "RAW", "PreBlackone", pedited, raw.bayersensor.black1, pedited->raw.bayersensor.exBlack1); assignFromKeyfile(keyFile, "RAW", "PreBlacktwo", pedited, raw.bayersensor.black2, pedited->raw.bayersensor.exBlack2); diff --git a/rtgui/addsetids.h b/rtgui/addsetids.h index c5913a6e2..15c6ba078 100644 --- a/rtgui/addsetids.h +++ b/rtgui/addsetids.h @@ -136,6 +136,13 @@ enum { ADDSET_FATTAL_ANCHOR, ADDSET_SHARPENMICRO_CONTRAST, ADDSET_SHARP_CONTRAST, + ADDSET_BAYER_FALSE_COLOR_SUPPRESSION, + ADDSET_BAYER_ITER, + ADDSET_BAYER_PS_SMOOTH, + ADDSET_BAYER_PS_EPERISO, + ADDSET_BAYER_PS_SIGMA, + ADDSET_BAYER_DUALDEMOZCONTRAST, + ADDSET_XTRANS_FALSE_COLOR_SUPPRESSION, ADDSET_PARAM_NUM // THIS IS USED AS A DELIMITER!! }; diff --git a/rtgui/batchtoolpanelcoord.cc b/rtgui/batchtoolpanelcoord.cc index 856f3a112..81f61471e 100644 --- a/rtgui/batchtoolpanelcoord.cc +++ b/rtgui/batchtoolpanelcoord.cc @@ -164,6 +164,8 @@ void BatchToolPanelCoordinator::initSession () dirpyrequalizer->setAdjusterBehavior (false, false, false); wavelet->setAdjusterBehavior (false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false); dirpyrdenoise->setAdjusterBehavior (false, false, false, false, false, false, false); + bayerprocess->setAdjusterBehavior(false, false, false, false, false, false); + xtransprocess->setAdjusterBehavior(false); bayerpreprocess->setAdjusterBehavior (false, false); rawcacorrection->setAdjusterBehavior (false); flatfield->setAdjusterBehavior(false); @@ -209,6 +211,8 @@ void BatchToolPanelCoordinator::initSession () dirpyrequalizer->setAdjusterBehavior (options.baBehav[ADDSET_DIRPYREQ], options.baBehav[ADDSET_DIRPYREQ_THRESHOLD], options.baBehav[ADDSET_DIRPYREQ_SKINPROTECT]); wavelet->setAdjusterBehavior (options.baBehav[ADDSET_WA], options.baBehav[ADDSET_WA_THRESHOLD], options.baBehav[ADDSET_WA_THRESHOLD2], options.baBehav[ADDSET_WA_THRES], options.baBehav[ADDSET_WA_CHRO], options.baBehav[ADDSET_WA_CHROMA], options.baBehav[ADDSET_WA_CONTRAST], options.baBehav[ADDSET_WA_SKINPROTECT], options.baBehav[ADDSET_WA_RESCHRO], options.baBehav[ADDSET_WA_TMRS], options.baBehav[ADDSET_WA_RESCON], options.baBehav[ADDSET_WA_RESCONH], options.baBehav[ADDSET_WA_THRR], options.baBehav[ADDSET_WA_THRRH], options.baBehav[ADDSET_WA_SKYPROTECT], options.baBehav[ADDSET_WA_EDGRAD], options.baBehav[ADDSET_WA_EDGVAL], options.baBehav[ADDSET_WA_STRENGTH], options.baBehav[ADDSET_WA_GAMMA], options.baBehav[ADDSET_WA_EDGEDETECT], options.baBehav[ADDSET_WA_EDGEDETECTTHR], options.baBehav[ADDSET_WA_EDGEDETECTTHR2]); dirpyrdenoise->setAdjusterBehavior (options.baBehav[ADDSET_DIRPYRDN_LUMA], options.baBehav[ADDSET_DIRPYRDN_LUMDET], options.baBehav[ADDSET_DIRPYRDN_CHROMA], options.baBehav[ADDSET_DIRPYRDN_CHROMARED], options.baBehav[ADDSET_DIRPYRDN_CHROMABLUE], options.baBehav[ADDSET_DIRPYRDN_GAMMA], options.baBehav[ADDSET_DIRPYRDN_PASSES]); + bayerprocess->setAdjusterBehavior(options.baBehav[ADDSET_BAYER_FALSE_COLOR_SUPPRESSION], options.baBehav[ADDSET_BAYER_ITER], options.baBehav[ADDSET_BAYER_DUALDEMOZCONTRAST], options.baBehav[ADDSET_BAYER_PS_SIGMA], options.baBehav[ADDSET_BAYER_PS_SMOOTH], options.baBehav[ADDSET_BAYER_PS_EPERISO]); + xtransprocess->setAdjusterBehavior(options.baBehav[ADDSET_BAYER_FALSE_COLOR_SUPPRESSION]); bayerpreprocess->setAdjusterBehavior (options.baBehav[ADDSET_PREPROCESS_LINEDENOISE], options.baBehav[ADDSET_PREPROCESS_GREENEQUIL]); rawcacorrection->setAdjusterBehavior (options.baBehav[ADDSET_RAWCACORR]); flatfield->setAdjusterBehavior(options.baBehav[ADDSET_RAWFFCLIPCONTROL]); @@ -349,6 +353,13 @@ void BatchToolPanelCoordinator::initSession () pparams.raw.bayersensor.black0 = pparams.raw.bayersensor.black1 = pparams.raw.bayersensor.black2 = pparams.raw.bayersensor.black3 = pparams.raw.xtranssensor.blackred = pparams.raw.xtranssensor.blackgreen = pparams.raw.xtranssensor.blackblue = 0; } + if (options.baBehav[ADDSET_BAYER_FALSE_COLOR_SUPPRESSION]) { pparams.raw.bayersensor.ccSteps = 0; } + if (options.baBehav[ADDSET_BAYER_ITER]) { pparams.raw.bayersensor.dcb_iterations = 0; pparams.raw.bayersensor.lmmse_iterations = 0; } + if (options.baBehav[ADDSET_BAYER_PS_SMOOTH]) { pparams.raw.bayersensor.pixelShiftSmoothFactor = 0; } + if (options.baBehav[ADDSET_BAYER_PS_EPERISO]) { pparams.raw.bayersensor.pixelShiftEperIso = 0; } + if (options.baBehav[ADDSET_BAYER_PS_SIGMA]) { pparams.raw.bayersensor.pixelShiftSigma = 0; } + if (options.baBehav[ADDSET_BAYER_DUALDEMOZCONTRAST]) { pparams.raw.bayersensor.dualDemosaicContrast = 0; } + if (options.baBehav[ADDSET_XTRANS_FALSE_COLOR_SUPPRESSION]) { pparams.raw.xtranssensor.ccSteps = 0; } if (options.baBehav[ADDSET_RAWFFCLIPCONTROL]) { pparams.raw.ff_clipControl = 0; } if (options.baBehav[ADDSET_PREPROCESS_GREENEQUIL]) { pparams.raw.bayersensor.greenthresh = 0; } if (options.baBehav[ADDSET_PREPROCESS_LINEDENOISE]) { pparams.raw.bayersensor.linenoise = 0; } diff --git a/rtgui/bayerprocess.cc b/rtgui/bayerprocess.cc index d08ec0393..339666aa0 100644 --- a/rtgui/bayerprocess.cc +++ b/rtgui/bayerprocess.cc @@ -307,31 +307,11 @@ void BayerProcess::read(const rtengine::procparams::ProcParams* pp, const Params } if (!batchMode) { - if (pp->raw.bayersensor.method == procparams::RAWParams::BayerSensor::getMethodString(procparams::RAWParams::BayerSensor::Method::DCB) || - method->get_active_row_number() == std::numeric_limits::max()) { - dcbOptions->show(); - } else { - dcbOptions->hide(); - } - if (pp->raw.bayersensor.method == procparams::RAWParams::BayerSensor::getMethodString(procparams::RAWParams::BayerSensor::Method::LMMSE) || - method->get_active_row_number() == std::numeric_limits::max()) { - lmmseOptions->show(); - } else { - lmmseOptions->hide(); - } - if (pp->raw.bayersensor.method == procparams::RAWParams::BayerSensor::getMethodString(procparams::RAWParams::BayerSensor::Method::AMAZEVNG4) || - method->get_active_row_number() == std::numeric_limits::max()) { - dualDemosaicOptions->show(); - } else { - dualDemosaicOptions->hide(); - } - if (pp->raw.bayersensor.method == procparams::RAWParams::BayerSensor::getMethodString(procparams::RAWParams::BayerSensor::Method::PIXELSHIFT) || - method->get_active_row_number() == std::numeric_limits::max()) { - if(pp->raw.bayersensor.pixelShiftMotionCorrectionMethod == RAWParams::BayerSensor::PSMotionCorrectionMethod::CUSTOM) { - pixelShiftOptions->show(); - } else { - pixelShiftOptions->hide(); - } + dcbOptions->set_visible(pp->raw.bayersensor.method == procparams::RAWParams::BayerSensor::getMethodString(procparams::RAWParams::BayerSensor::Method::DCB)); + lmmseOptions->set_visible(pp->raw.bayersensor.method == procparams::RAWParams::BayerSensor::getMethodString(procparams::RAWParams::BayerSensor::Method::LMMSE)); + dualDemosaicOptions->set_visible(pp->raw.bayersensor.method == procparams::RAWParams::BayerSensor::getMethodString(procparams::RAWParams::BayerSensor::Method::AMAZEVNG4)); + if (pp->raw.bayersensor.method == procparams::RAWParams::BayerSensor::getMethodString(procparams::RAWParams::BayerSensor::Method::PIXELSHIFT)) { + pixelShiftOptions->set_visible(pp->raw.bayersensor.pixelShiftMotionCorrectionMethod == RAWParams::BayerSensor::PSMotionCorrectionMethod::CUSTOM); pixelShiftFrame->show(); } else { pixelShiftFrame->hide(); @@ -415,6 +395,28 @@ void BayerProcess::write( rtengine::procparams::ProcParams* pp, ParamsEdited* pe } } +void BayerProcess::setAdjusterBehavior (bool falsecoloradd, bool iteradd, bool dualdemozecontrastadd, bool pssigmaadd, bool pssmoothadd, bool pseperisoadd) +{ + ccSteps->setAddMode(falsecoloradd); + dcbIterations->setAddMode(iteradd); + lmmseIterations->setAddMode(iteradd); + pixelShiftSmooth->setAddMode(pssmoothadd); + pixelShiftEperIso->setAddMode(pseperisoadd); + pixelShiftSigma->setAddMode(pssigmaadd); + dualDemosaicContrast->setAddMode(dualdemozecontrastadd); +} + +void BayerProcess::trimValues (rtengine::procparams::ProcParams* pp) +{ + ccSteps->trimValue(pp->raw.bayersensor.ccSteps); + dcbIterations->trimValue(pp->raw.bayersensor.dcb_iterations); + lmmseIterations->trimValue(pp->raw.bayersensor.lmmse_iterations); + pixelShiftSmooth->trimValue(pp->raw.bayersensor.pixelShiftSmoothFactor); + pixelShiftEperIso->trimValue(pp->raw.bayersensor.pixelShiftEperIso); + pixelShiftSigma->trimValue(pp->raw.bayersensor.pixelShiftSigma); + dualDemosaicContrast->trimValue(pp->raw.bayersensor.dualDemosaicContrast); +} + void BayerProcess::setBatchMode(bool batchMode) { method->append (M("GENERAL_UNCHANGED")); diff --git a/rtgui/bayerprocess.h b/rtgui/bayerprocess.h index 84701a52e..ee532f27c 100644 --- a/rtgui/bayerprocess.h +++ b/rtgui/bayerprocess.h @@ -65,15 +65,17 @@ public: BayerProcess (); - void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited = nullptr); - void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited = nullptr); - void setBatchMode (bool batchMode); - void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited = nullptr); + void read(const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited = nullptr); + void write(rtengine::procparams::ProcParams* pp, ParamsEdited* pedited = nullptr); + void setAdjusterBehavior(bool falsecoloradd, bool iteradd, bool dualdemozecontrastadd, bool pssigmaadd, bool pssmoothadd, bool pseperisoadd); + void trimValues(rtengine::procparams::ProcParams* pp); + void setBatchMode(bool batchMode); + void setDefaults(const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited = nullptr); - void methodChanged (); - void imageNumberChanged (); - void adjusterChanged (Adjuster* a, double newval); - void checkBoxToggled (CheckBox* c, CheckValue newval); + void methodChanged(); + void imageNumberChanged(); + void adjusterChanged(Adjuster* a, double newval); + void checkBoxToggled(CheckBox* c, CheckValue newval); void pixelShiftMotionMethodChanged(); void FrameCountChanged(int n, int frameNum); }; diff --git a/rtgui/ppversion.h b/rtgui/ppversion.h index e9f7ad60e..2b6bc49de 100644 --- a/rtgui/ppversion.h +++ b/rtgui/ppversion.h @@ -1,11 +1,13 @@ #pragma once // This number has to be incremented whenever the PP3 file format is modified or the behaviour of a tool changes -#define PPVERSION 334 +#define PPVERSION 335 #define PPVERSION_AEXP 301 //value of PPVERSION when auto exposure algorithm was modified /* Log of version changes + 335 2018-05-30 + new contrast adjuster in Bayer process tool 334 2018-05-13 new contrast threshold adjuster in Microcontrast tool 333 2018-04-26 diff --git a/rtgui/preferences.cc b/rtgui/preferences.cc index 79cc6fd4c..623cb25d5 100644 --- a/rtgui/preferences.cc +++ b/rtgui/preferences.cc @@ -387,6 +387,19 @@ Gtk::Widget* Preferences::getBatchProcPanel () appendBehavList (mi, M ("TP_WAVELET_EDGEDETECTTHR"), ADDSET_WA_EDGEDETECTTHR, true); appendBehavList (mi, M ("TP_WAVELET_EDGEDETECTTHR2"), ADDSET_WA_EDGEDETECTTHR2, true); + mi = behModel->append (); + mi->set_value (behavColumns.label, M ("TP_RAW_SENSOR_BAYER_LABEL")); + appendBehavList (mi, M ("TP_RAW_FALSECOLOR"), ADDSET_BAYER_FALSE_COLOR_SUPPRESSION, false); + appendBehavList (mi, M ("TP_RAW_DCBITERATIONS") + ", " + M("TP_RAW_LMMSEITERATIONS"), ADDSET_BAYER_ITER, false); + appendBehavList (mi, M ("TP_RAW_DUALDEMOSAICCONTRAST"), ADDSET_BAYER_DUALDEMOZCONTRAST, false); + appendBehavList (mi, M ("TP_RAW_PIXELSHIFTSIGMA"), ADDSET_BAYER_PS_SIGMA, false); + appendBehavList (mi, M ("TP_RAW_PIXELSHIFTSMOOTH"), ADDSET_BAYER_PS_SMOOTH, false); + appendBehavList (mi, M ("TP_RAW_PIXELSHIFTEPERISO"), ADDSET_BAYER_PS_EPERISO, false); + + mi = behModel->append (); + mi->set_value (behavColumns.label, M ("TP_RAW_SENSOR_XTRANS_LABEL")); + appendBehavList (mi, M ("TP_RAW_FALSECOLOR"), ADDSET_XTRANS_FALSE_COLOR_SUPPRESSION, false); + mi = behModel->append (); mi->set_value (behavColumns.label, M ("TP_PREPROCESS_LABEL")); appendBehavList (mi, M ("TP_PREPROCESS_GREENEQUIL"), ADDSET_PREPROCESS_GREENEQUIL, false); diff --git a/rtgui/xtransprocess.cc b/rtgui/xtransprocess.cc index 9e0c94ea0..a001758f9 100644 --- a/rtgui/xtransprocess.cc +++ b/rtgui/xtransprocess.cc @@ -123,6 +123,11 @@ void XTransProcess::write( rtengine::procparams::ProcParams* pp, ParamsEdited* p } } +void XTransProcess::setAdjusterBehavior (bool falsecoloradd) +{ + ccSteps->setAddMode(falsecoloradd); +} + void XTransProcess::setBatchMode(bool batchMode) { method->append (M("GENERAL_UNCHANGED")); diff --git a/rtgui/xtransprocess.h b/rtgui/xtransprocess.h index 44ed2e670..274b52c29 100644 --- a/rtgui/xtransprocess.h +++ b/rtgui/xtransprocess.h @@ -40,13 +40,14 @@ public: XTransProcess (); - void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited = nullptr); - void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited = nullptr); - void setBatchMode (bool batchMode); - void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited = nullptr); + void read(const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited = nullptr); + void write(rtengine::procparams::ProcParams* pp, ParamsEdited* pedited = nullptr); + void setAdjusterBehavior(bool falsecoloradd); + void setBatchMode(bool batchMode); + void setDefaults(const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited = nullptr); - void methodChanged (); - void adjusterChanged (Adjuster* a, double newval); + void methodChanged(); + void adjusterChanged(Adjuster* a, double newval); }; #endif From 41c1f21c7687612fbd215322e26fb347b9482ba7 Mon Sep 17 00:00:00 2001 From: heckflosse Date: Fri, 1 Jun 2018 19:13:59 +0200 Subject: [PATCH 09/42] Pixelshift: replaced checkbox to use lmmse by a combobox to allow further demosaicers for parts with motion, #4579 --- rtdata/languages/default | 1 + rtengine/amaze_demosaic_RT.cc | 2 +- rtengine/amaze_vng4_demosaic_RT.cc | 12 +- rtengine/demosaic_algos.cc | 2 +- rtengine/demosaic_algos.cc.save-failed | 3861 ++++++++++++++++++++++++ rtengine/pixelshift.cc | 13 +- rtengine/procparams.cc | 43 +- rtengine/procparams.h | 11 +- rtengine/rawimagesource.cc | 2 +- rtengine/rawimagesource.h | 6 +- rtengine/simpleprocess.cc | 2 - rtgui/bayerprocess.cc | 66 +- rtgui/bayerprocess.h | 4 +- rtgui/paramsedited.cc | 14 +- rtgui/paramsedited.h | 2 +- rtgui/partialpastedlg.cc | 2 +- rtgui/ppversion.h | 4 +- 17 files changed, 3997 insertions(+), 50 deletions(-) create mode 100644 rtengine/demosaic_algos.cc.save-failed diff --git a/rtdata/languages/default b/rtdata/languages/default index 5f16404c2..8231932fb 100644 --- a/rtdata/languages/default +++ b/rtdata/languages/default @@ -1790,6 +1790,7 @@ TP_RAW_MONO;Mono TP_RAW_NONE;None (Shows sensor pattern) TP_RAW_PIXELSHIFT;Pixel Shift TP_RAW_PIXELSHIFTBLUR;Blur motion mask +TP_RAW_PIXELSHIFTDMETHOD;Demosaic method for motion TP_RAW_PIXELSHIFTEPERISO;Sensitivity TP_RAW_PIXELSHIFTEPERISO_TOOLTIP;The default value of 0 should work fine for base ISO.\nHigher values increase sensitivity of motion detection.\nChange in small steps and watch the motion mask while changing.\nIncrease sensitivity for underexposed or high ISO images. TP_RAW_PIXELSHIFTEQUALBRIGHT;Equalize brightness of frames diff --git a/rtengine/amaze_demosaic_RT.cc b/rtengine/amaze_demosaic_RT.cc index 4fe0bee69..1e1b97768 100644 --- a/rtengine/amaze_demosaic_RT.cc +++ b/rtengine/amaze_demosaic_RT.cc @@ -38,7 +38,7 @@ namespace rtengine { -void RawImageSource::amaze_demosaic_RT(int winx, int winy, int winw, int winh, array2D &rawData, array2D &red, array2D &green, array2D &blue) +void RawImageSource::amaze_demosaic_RT(int winx, int winy, int winw, int winh, const array2D &rawData, array2D &red, array2D &green, array2D &blue) { BENCHFUN diff --git a/rtengine/amaze_vng4_demosaic_RT.cc b/rtengine/amaze_vng4_demosaic_RT.cc index 0dae2c49b..841abf9d3 100644 --- a/rtengine/amaze_vng4_demosaic_RT.cc +++ b/rtengine/amaze_vng4_demosaic_RT.cc @@ -35,22 +35,24 @@ using namespace std; namespace rtengine { -void RawImageSource::amaze_vng4_demosaic_RT(int winw, int winh, array2D &rawData, array2D &red, array2D &green, array2D &blue, double contrast) +void RawImageSource::amaze_vng4_demosaic_RT(int winw, int winh, const array2D &rawData, array2D &red, array2D &green, array2D &blue, double contrast) { BENCHFUN if (contrast == 0.0) { // contrast == 0.0 means only AMaZE will be used - amaze_demosaic_RT (0, 0, winw, winh, rawData, red, green, blue); + amaze_demosaic_RT(0, 0, winw, winh, rawData, red, green, blue); return; } - vng4_demosaic (); + vng4_demosaic(rawData, red, green, blue); + array2D redTmp(winw, winh); array2D greenTmp(winw, winh); array2D blueTmp(winw, winh); array2D L(winw, winh); - amaze_demosaic_RT (0, 0, winw, winh, rawData, redTmp, greenTmp, blueTmp); + + amaze_demosaic_RT(0, 0, winw, winh, rawData, redTmp, greenTmp, blueTmp); const float xyz_rgb[3][3] = { // XYZ from RGB { 0.412453, 0.357580, 0.180423 }, { 0.212671, 0.715160, 0.072169 }, @@ -63,7 +65,7 @@ void RawImageSource::amaze_vng4_demosaic_RT(int winw, int winh, array2D & Color::RGB2L(redTmp[i], greenTmp[i], blueTmp[i], L[i], xyz_rgb, winw); } } - // calculate contrast based blend factors to reduce sharpening in regions with low contrast + // calculate contrast based blend factors to use vng4 in regions with low contrast JaggedArray blend(winw, winh); buildBlendMask(L, blend, winw, winh, contrast / 100.f); diff --git a/rtengine/demosaic_algos.cc b/rtengine/demosaic_algos.cc index 582b00629..d0f4eebd8 100644 --- a/rtengine/demosaic_algos.cc +++ b/rtengine/demosaic_algos.cc @@ -562,7 +562,7 @@ void RawImageSource::hphd_demosaic () //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% #define fc(row,col) (prefilters >> ((((row) << 1 & 14) + ((col) & 1)) << 1) & 3) typedef unsigned short ushort; -void RawImageSource::vng4_demosaic () +void RawImageSource::vng4_demosaic (const array2D &rawData, array2D &red, array2D &green, array2D &blue) { const signed short int *cp, terms[] = { -2, -2, +0, -1, 0, 0x01, -2, -2, +0, +0, 1, 0x01, -2, -1, -1, +0, 0, 0x01, diff --git a/rtengine/demosaic_algos.cc.save-failed b/rtengine/demosaic_algos.cc.save-failed new file mode 100644 index 000000000..29ee67332 --- /dev/null +++ b/rtengine/demosaic_algos.cc.save-failed @@ -0,0 +1,3861 @@ +/* + * This file is part of RawTherapee. + * + * Copyright (c) 2004-2010 Gabor Horvath + * + * 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 +#include + +#include "rawimagesource.h" +#include "rawimagesource_i.h" +#include "jaggedarray.h" +#include "rawimage.h" +#include "mytime.h" +#include "iccmatrices.h" +#include "iccstore.h" +#include "image8.h" +#include "curves.h" +#include "dfmanager.h" +#include "slicer.h" +#include "rt_math.h" +#include "color.h" +#include "../rtgui/multilangmgr.h" +#include "procparams.h" +#include "sleef.c" +#include "opthelper.h" +#include "median.h" +#include "StopWatch.h" +#ifdef _OPENMP +#include +#endif + +using namespace std; + +namespace rtengine +{ +#undef ABS +#undef DIST + +#define ABS(a) ((a)<0?-(a):(a)) +#define DIST(a,b) (ABS(a-b)) +#define CLIREF(x) LIM(x,-200000.0f,200000.0f) // avoid overflow : do not act directly on image[] or pix[] +#define x1125(a) (a + xdivf(a, 3)) +#define x0875(a) (a - xdivf(a, 3)) +#define x0250(a) xdivf(a, 2) +#define x00625(a) xdivf(a, 4) +#define x0125(a) xdivf(a, 3) + +extern const Settings* settings; +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +void RawImageSource::eahd_demosaic () +{ + if (plistener) { + plistener->setProgressStr (Glib::ustring::compose(M("TP_RAW_DMETHOD_PROGRESSBAR"), RAWParams::BayerSensor::getMethodString(RAWParams::BayerSensor::Method::EAHD))); + plistener->setProgress (0.0); + } + + // prepare cache and constants for cielab conversion + //TODO: revisit after conversion to D50 illuminant + lc00 = (0.412453 * imatrices.rgb_cam[0][0] + 0.357580 * imatrices.rgb_cam[0][1] + 0.180423 * imatrices.rgb_cam[0][2]) ;// / 0.950456; + lc01 = (0.412453 * imatrices.rgb_cam[1][0] + 0.357580 * imatrices.rgb_cam[1][1] + 0.180423 * imatrices.rgb_cam[1][2]) ;// / 0.950456; + lc02 = (0.412453 * imatrices.rgb_cam[2][0] + 0.357580 * imatrices.rgb_cam[2][1] + 0.180423 * imatrices.rgb_cam[2][2]) ;// / 0.950456; + + lc10 = 0.212671 * imatrices.rgb_cam[0][0] + 0.715160 * imatrices.rgb_cam[0][1] + 0.072169 * imatrices.rgb_cam[0][2]; + lc11 = 0.212671 * imatrices.rgb_cam[1][0] + 0.715160 * imatrices.rgb_cam[1][1] + 0.072169 * imatrices.rgb_cam[1][2]; + lc12 = 0.212671 * imatrices.rgb_cam[2][0] + 0.715160 * imatrices.rgb_cam[2][1] + 0.072169 * imatrices.rgb_cam[2][2]; + + lc20 = (0.019334 * imatrices.rgb_cam[0][0] + 0.119193 * imatrices.rgb_cam[0][1] + 0.950227 * imatrices.rgb_cam[0][2]) ;// / 1.088754; + lc21 = (0.019334 * imatrices.rgb_cam[1][0] + 0.119193 * imatrices.rgb_cam[1][1] + 0.950227 * imatrices.rgb_cam[1][2]) ;// / 1.088754; + lc22 = (0.019334 * imatrices.rgb_cam[2][0] + 0.119193 * imatrices.rgb_cam[2][1] + 0.950227 * imatrices.rgb_cam[2][2]) ;// / 1.088754; + + int maxindex = 3 * 65536; //2*65536 3 = avoid crash 3/2013 J.Desmis + cache = new double[maxindex]; + threshold = (int)(0.008856 * MAXVALD); + + for (int i = 0; i < maxindex; i++) { + cache[i] = std::cbrt(double(i) / MAXVALD); + } + + // end of cielab preparation + + JaggedArray + rh (W, 3), gh (W, 4), bh (W, 3), + rv (W, 3), gv (W, 4), bv (W, 3), + lLh (W, 3), lah (W, 3), lbh (W, 3), + lLv (W, 3), lav (W, 3), lbv (W, 3), + homh (W, 3), homv (W, 3); + + // interpolate first two lines + interpolate_row_g (gh[0], gv[0], 0); + interpolate_row_g (gh[1], gv[1], 1); + interpolate_row_g (gh[2], gv[2], 2); + interpolate_row_rb (rh[0], bh[0], nullptr, gh[0], gh[1], 0); + interpolate_row_rb (rv[0], bv[0], nullptr, gv[0], gv[1], 0); + interpolate_row_rb (rh[1], bh[1], gh[0], gh[1], gh[2], 1); + interpolate_row_rb (rv[1], bv[1], gv[0], gv[1], gv[2], 1); + + convert_to_cielab_row (rh[0], gh[0], bh[0], lLh[0], lah[0], lbh[0]); + convert_to_cielab_row (rv[0], gv[0], bv[0], lLv[0], lav[0], lbv[0]); + convert_to_cielab_row (rh[1], gh[1], bh[1], lLh[1], lah[1], lbh[1]); + convert_to_cielab_row (rv[1], gv[1], bv[1], lLv[1], lav[1], lbv[1]); + + for (int j = 0; j < W; j++) { + homh[0][j] = 0; + homv[0][j] = 0; + homh[1][j] = 0; + homv[1][j] = 0; + } + + int dLmaph[9]; + int dLmapv[9]; + int dCamaph[9]; + int dCamapv[9]; + int dCbmaph[9]; + int dCbmapv[9]; + + for (int i = 1; i < H - 1; i++) { + int ix = i % 3; + int imx = (i - 1) % 3; + int ipx = (i + 1) % 3; + + if (i < H - 2) { + interpolate_row_g (gh[(i + 2) % 4], gv[(i + 2) % 4], i + 2); + interpolate_row_rb (rh[(i + 1) % 3], bh[(i + 1) % 3], gh[i % 4], gh[(i + 1) % 4], gh[(i + 2) % 4], i + 1); + interpolate_row_rb (rv[(i + 1) % 3], bv[(i + 1) % 3], gv[i % 4], gv[(i + 1) % 4], gv[(i + 2) % 4], i + 1); + } else { + interpolate_row_rb (rh[(i + 1) % 3], bh[(i + 1) % 3], gh[i % 4], gh[(i + 1) % 4], nullptr, i + 1); + interpolate_row_rb (rv[(i + 1) % 3], bv[(i + 1) % 3], gv[i % 4], gv[(i + 1) % 4], nullptr, i + 1); + } + + convert_to_cielab_row (rh[(i + 1) % 3], gh[(i + 1) % 4], bh[(i + 1) % 3], lLh[(i + 1) % 3], lah[(i + 1) % 3], lbh[(i + 1) % 3]); + convert_to_cielab_row (rv[(i + 1) % 3], gv[(i + 1) % 4], bv[(i + 1) % 3], lLv[(i + 1) % 3], lav[(i + 1) % 3], lbv[(i + 1) % 3]); + + for (int j = 0; j < W; j++) { + homh[ipx][j] = 0; + homv[ipx][j] = 0; + } + + int sh, sv, idx; + + for (int j = 1; j < W - 1; j++) { + int dmi = 0; + + for (int x = -1; x <= 1; x++) { + idx = (i + x) % 3; + + for (int y = -1; y <= 1; y++) { + // compute distance in a, b, and L + if (dmi < 4) { + sh = homh[idx][j + y]; + sv = homv[idx][j + y]; + + if (sh > sv) { // fixate horizontal pixel + dLmaph[dmi] = DIST(lLh[ix][j], lLh[idx][j + y]); + dCamaph[dmi] = DIST(lah[ix][j], lah[idx][j + y]); + dCbmaph[dmi] = DIST(lbh[ix][j], lbh[idx][j + y]); + dLmapv[dmi] = DIST(lLv[ix][j], lLh[idx][j + y]); + dCamapv[dmi] = DIST(lav[ix][j], lah[idx][j + y]); + dCbmapv[dmi] = DIST(lbv[ix][j], lbh[idx][j + y]); + } else if (sh < sv) { + dLmaph[dmi] = DIST(lLh[ix][j], lLv[idx][j + y]); + dCamaph[dmi] = DIST(lah[ix][j], lav[idx][j + y]); + dCbmaph[dmi] = DIST(lbh[ix][j], lbv[idx][j + y]); + dLmapv[dmi] = DIST(lLv[ix][j], lLv[idx][j + y]); + dCamapv[dmi] = DIST(lav[ix][j], lav[idx][j + y]); + dCbmapv[dmi] = DIST(lbv[ix][j], lbv[idx][j + y]); + } else { + dLmaph[dmi] = DIST(lLh[ix][j], lLh[idx][j + y]); + dCamaph[dmi] = DIST(lah[ix][j], lah[idx][j + y]); + dCbmaph[dmi] = DIST(lbh[ix][j], lbh[idx][j + y]); + dLmapv[dmi] = DIST(lLv[ix][j], lLv[idx][j + y]); + dCamapv[dmi] = DIST(lav[ix][j], lav[idx][j + y]); + dCbmapv[dmi] = DIST(lbv[ix][j], lbv[idx][j + y]); + } + } else { + dLmaph[dmi] = DIST(lLh[ix][j], lLh[idx][j + y]); + dCamaph[dmi] = DIST(lah[ix][j], lah[idx][j + y]); + dCbmaph[dmi] = DIST(lbh[ix][j], lbh[idx][j + y]); + dLmapv[dmi] = DIST(lLv[ix][j], lLv[idx][j + y]); + dCamapv[dmi] = DIST(lav[ix][j], lav[idx][j + y]); + dCbmapv[dmi] = DIST(lbv[ix][j], lbv[idx][j + y]); + } + + dmi++; + } + } + + // compute eL & eC + int eL = min(max(dLmaph[3], dLmaph[5]), max(dLmapv[1], dLmapv[7])); + int eCa = min(max(dCamaph[3], dCamaph[5]), max(dCamapv[1], dCamapv[7])); + int eCb = min(max(dCbmaph[3], dCbmaph[5]), max(dCbmapv[1], dCbmapv[7])); + + int wh = 0; + + for (int dmi = 0; dmi < 9; dmi++) + if (dLmaph[dmi] <= eL && dCamaph[dmi] <= eCa && dCbmaph[dmi] <= eCb) { + wh++; + } + + int wv = 0; + + for (int dmi = 0; dmi < 9; dmi++) + if (dLmapv[dmi] <= eL && dCamapv[dmi] <= eCa && dCbmapv[dmi] <= eCb) { + wv++; + } + + homh[imx][j - 1] += wh; + homh[imx][j] += wh; + homh[imx][j + 1] += wh; + homh[ix][j - 1] += wh; + homh[ix][j] += wh; + homh[ix][j + 1] += wh; + homh[ipx][j - 1] += wh; + homh[ipx][j] += wh; + homh[ipx][j + 1] += wh; + + homv[imx][j - 1] += wv; + homv[imx][j] += wv; + homv[imx][j + 1] += wv; + homv[ix][j - 1] += wv; + homv[ix][j] += wv; + homv[ix][j + 1] += wv; + homv[ipx][j - 1] += wv; + homv[ipx][j] += wv; + homv[ipx][j + 1] += wv; + } + +//} + // finalize image + int hc, vc; + + for (int j = 0; j < W; j++) { + if (ri->ISGREEN(i - 1, j)) { + green[i - 1][j] = rawData[i - 1][j]; + } else { + hc = homh[imx][j]; + vc = homv[imx][j]; + + if (hc > vc) { + green[i - 1][j] = gh[(i - 1) % 4][j]; + } else if (hc < vc) { + green[i - 1][j] = gv[(i - 1) % 4][j]; + } else { + green[i - 1][j] = (gh[(i - 1) % 4][j] + gv[(i - 1) % 4][j]) / 2; + } + } + } + + if (!(i % 20) && plistener) { + plistener->setProgress ((double)i / (H - 2)); + } + } + + // finish H-2th and H-1th row, homogenity value is still valailable + int hc, vc; + + for (int i = H - 1; i < H + 1; i++) + for (int j = 0; j < W; j++) { + hc = homh[(i - 1) % 3][j]; + vc = homv[(i - 1) % 3][j]; + + if (hc > vc) { + green[i - 1][j] = gh[(i - 1) % 4][j]; + } else if (hc < vc) { + green[i - 1][j] = gv[(i - 1) % 4][j]; + } else { + green[i - 1][j] = (gh[(i - 1) % 4][j] + gv[(i - 1) % 4][j]) / 2; + } + } + + // Interpolate R and B + for (int i = 0; i < H; i++) { + if (i == 0) { + interpolate_row_rb_mul_pp (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 (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 (red[i], blue[i], green[i - 1], green[i], green[i + 1], i, 1.0, 1.0, 1.0, 0, W, 1); + } + } +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +void RawImageSource::hphd_vertical (float** hpmap, int col_from, int col_to) +{ + float* temp = new float[max(W, H)]; + float* avg = new float[max(W, H)]; + float* dev = new float[max(W, H)]; + + memset (temp, 0, max(W, H)*sizeof(float)); + memset (avg, 0, max(W, H)*sizeof(float)); + memset (dev, 0, max(W, H)*sizeof(float)); + + for (int k = col_from; k < col_to; k++) { + for (int i = 5; i < H - 5; i++) { + temp[i] = (rawData[i - 5][k] - 8 * rawData[i - 4][k] + 27 * rawData[i - 3][k] - 48 * rawData[i - 2][k] + 42 * rawData[i - 1][k] - + (rawData[i + 5][k] - 8 * rawData[i + 4][k] + 27 * rawData[i + 3][k] - 48 * rawData[i + 2][k] + 42 * rawData[i + 1][k])) / 100.0; + temp[i] = ABS(temp[i]); + } + + for (int j = 4; j < H - 4; j++) { + float avgL = (temp[j - 4] + temp[j - 3] + temp[j - 2] + temp[j - 1] + temp[j] + temp[j + 1] + temp[j + 2] + temp[j + 3] + temp[j + 4]) / 9.0; + avg[j] = avgL; + float devL = ((temp[j - 4] - avgL) * (temp[j - 4] - avgL) + (temp[j - 3] - avgL) * (temp[j - 3] - avgL) + (temp[j - 2] - avgL) * (temp[j - 2] - avgL) + (temp[j - 1] - avgL) * (temp[j - 1] - avgL) + (temp[j] - avgL) * (temp[j] - avgL) + (temp[j + 1] - avgL) * (temp[j + 1] - avgL) + (temp[j + 2] - avgL) * (temp[j + 2] - avgL) + (temp[j + 3] - avgL) * (temp[j + 3] - avgL) + (temp[j + 4] - avgL) * (temp[j + 4] - avgL)) / 9.0; + + if (devL < 0.001) { + devL = 0.001; + } + + dev[j] = devL; + } + + for (int j = 5; j < H - 5; j++) { + float avgL = avg[j - 1]; + float avgR = avg[j + 1]; + float devL = dev[j - 1]; + float devR = dev[j + 1]; + hpmap[j][k] = avgL + (avgR - avgL) * devL / (devL + devR); + } + } + + delete [] temp; + delete [] avg; + delete [] dev; +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +void RawImageSource::hphd_horizontal (float** hpmap, int row_from, int row_to) +{ + float* temp = new float[max(W, H)]; + float* avg = new float[max(W, H)]; + float* dev = new float[max(W, H)]; + + memset (temp, 0, max(W, H)*sizeof(float)); + memset (avg, 0, max(W, H)*sizeof(float)); + memset (dev, 0, max(W, H)*sizeof(float)); + + for (int i = row_from; i < row_to; i++) { + for (int j = 5; j < W - 5; j++) { + temp[j] = (rawData[i][j - 5] - 8 * rawData[i][j - 4] + 27 * rawData[i][j - 3] - 48 * rawData[i][j - 2] + 42 * rawData[i][j - 1] - + (rawData[i][j + 5] - 8 * rawData[i][j + 4] + 27 * rawData[i][j + 3] - 48 * rawData[i][j + 2] + 42 * rawData[i][j + 1])) / 100; + temp[j] = ABS(temp[j]); + } + + for (int j = 4; j < W - 4; j++) { + float avgL = (temp[j - 4] + temp[j - 3] + temp[j - 2] + temp[j - 1] + temp[j] + temp[j + 1] + temp[j + 2] + temp[j + 3] + temp[j + 4]) / 9.0; + avg[j] = avgL; + float devL = ((temp[j - 4] - avgL) * (temp[j - 4] - avgL) + (temp[j - 3] - avgL) * (temp[j - 3] - avgL) + (temp[j - 2] - avgL) * (temp[j - 2] - avgL) + (temp[j - 1] - avgL) * (temp[j - 1] - avgL) + (temp[j] - avgL) * (temp[j] - avgL) + (temp[j + 1] - avgL) * (temp[j + 1] - avgL) + (temp[j + 2] - avgL) * (temp[j + 2] - avgL) + (temp[j + 3] - avgL) * (temp[j + 3] - avgL) + (temp[j + 4] - avgL) * (temp[j + 4] - avgL)) / 9.0; + + if (devL < 0.001) { + devL = 0.001; + } + + dev[j] = devL; + } + + for (int j = 5; j < W - 5; j++) { + float avgL = avg[j - 1]; + float avgR = avg[j + 1]; + float devL = dev[j - 1]; + float devR = dev[j + 1]; + float hpv = avgL + (avgR - avgL) * devL / (devL + devR); + + if (hpmap[i][j] < 0.8 * hpv) { + hpmap[i][j] = 2; + } else if (hpv < 0.8 * hpmap[i][j]) { + hpmap[i][j] = 1; + } else { + hpmap[i][j] = 0; + } + } + } + + delete [] temp; + delete [] avg; + delete [] dev; +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +void RawImageSource::hphd_green (float** hpmap) +{ +#ifdef _OPENMP + #pragma omp parallel for +#endif + + for (int i = 3; i < H - 3; i++) { + for (int j = 3; j < W - 3; j++) { + if (ri->ISGREEN(i, j)) { + green[i][j] = rawData[i][j]; + } else { + if (hpmap[i][j] == 1) { + int g2 = rawData[i][j + 1] + ((rawData[i][j] - rawData[i][j + 2]) / 2); + int g4 = rawData[i][j - 1] + ((rawData[i][j] - rawData[i][j - 2]) / 2); + + int dx = rawData[i][j + 1] - rawData[i][j - 1]; + int d1 = rawData[i][j + 3] - rawData[i][j + 1]; + int d2 = rawData[i][j + 2] - rawData[i][j]; + int d3 = (rawData[i - 1][j + 2] - rawData[i - 1][j]) / 2; + int d4 = (rawData[i + 1][j + 2] - rawData[i + 1][j]) / 2; + + double e2 = 1.0 / (1.0 + ABS(dx) + ABS(d1) + ABS(d2) + ABS(d3) + ABS(d4)); + + d1 = rawData[i][j - 3] - rawData[i][j - 1]; + d2 = rawData[i][j - 2] - rawData[i][j]; + d3 = (rawData[i - 1][j - 2] - rawData[i - 1][j]) / 2; + d4 = (rawData[i + 1][j - 2] - rawData[i + 1][j]) / 2; + + double e4 = 1.0 / (1.0 + ABS(dx) + ABS(d1) + ABS(d2) + ABS(d3) + ABS(d4)); + + green[i][j] = (e2 * g2 + e4 * g4) / (e2 + e4); + } else if (hpmap[i][j] == 2) { + int g1 = rawData[i - 1][j] + ((rawData[i][j] - rawData[i - 2][j]) / 2); + int g3 = rawData[i + 1][j] + ((rawData[i][j] - rawData[i + 2][j]) / 2); + + int dy = rawData[i + 1][j] - rawData[i - 1][j]; + int d1 = rawData[i - 1][j] - rawData[i - 3][j]; + int d2 = rawData[i][j] - rawData[i - 2][j]; + int d3 = (rawData[i][j - 1] - rawData[i - 2][j - 1]) / 2; + int d4 = (rawData[i][j + 1] - rawData[i - 2][j + 1]) / 2; + + double e1 = 1.0 / (1.0 + ABS(dy) + ABS(d1) + ABS(d2) + ABS(d3) + ABS(d4)); + + d1 = rawData[i + 1][j] - rawData[i + 3][j]; + d2 = rawData[i][j] - rawData[i + 2][j]; + d3 = (rawData[i][j - 1] - rawData[i + 2][j - 1]) / 2; + d4 = (rawData[i][j + 1] - rawData[i + 2][j + 1]) / 2; + + double e3 = 1.0 / (1.0 + ABS(dy) + ABS(d1) + ABS(d2) + ABS(d3) + ABS(d4)); + + green[i][j] = (e1 * g1 + e3 * g3) / (e1 + e3); + } else { + int g1 = rawData[i - 1][j] + ((rawData[i][j] - rawData[i - 2][j]) / 2); + int g2 = rawData[i][j + 1] + ((rawData[i][j] - rawData[i][j + 2]) / 2); + int g3 = rawData[i + 1][j] + ((rawData[i][j] - rawData[i + 2][j]) / 2); + int g4 = rawData[i][j - 1] + ((rawData[i][j] - rawData[i][j - 2]) / 2); + + int dx = rawData[i][j + 1] - rawData[i][j - 1]; + int dy = rawData[i + 1][j] - rawData[i - 1][j]; + + int d1 = rawData[i - 1][j] - rawData[i - 3][j]; + int d2 = rawData[i][j] - rawData[i - 2][j]; + int d3 = (rawData[i][j - 1] - rawData[i - 2][j - 1]) / 2; + int d4 = (rawData[i][j + 1] - rawData[i - 2][j + 1]) / 2; + + double e1 = 1.0 / (1.0 + ABS(dy) + ABS(d1) + ABS(d2) + ABS(d3) + ABS(d4)); + + d1 = rawData[i][j + 3] - rawData[i][j + 1]; + d2 = rawData[i][j + 2] - rawData[i][j]; + d3 = (rawData[i - 1][j + 2] - rawData[i - 1][j]) / 2; + d4 = (rawData[i + 1][j + 2] - rawData[i + 1][j]) / 2; + + double e2 = 1.0 / (1.0 + ABS(dx) + ABS(d1) + ABS(d2) + ABS(d3) + ABS(d4)); + + d1 = rawData[i + 1][j] - rawData[i + 3][j]; + d2 = rawData[i][j] - rawData[i + 2][j]; + d3 = (rawData[i][j - 1] - rawData[i + 2][j - 1]) / 2; + d4 = (rawData[i][j + 1] - rawData[i + 2][j + 1]) / 2; + + double e3 = 1.0 / (1.0 + ABS(dy) + ABS(d1) + ABS(d2) + ABS(d3) + ABS(d4)); + + d1 = rawData[i][j - 3] - rawData[i][j - 1]; + d2 = rawData[i][j - 2] - rawData[i][j]; + d3 = (rawData[i - 1][j - 2] - rawData[i - 1][j]) / 2; + d4 = (rawData[i + 1][j - 2] - rawData[i + 1][j]) / 2; + + double e4 = 1.0 / (1.0 + ABS(dx) + ABS(d1) + ABS(d2) + ABS(d3) + ABS(d4)); + + green[i][j] = (e1 * g1 + e2 * g2 + e3 * g3 + e4 * g4) / (e1 + e2 + e3 + e4); + } + } + } + } +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +void RawImageSource::hphd_demosaic () +{ + if (plistener) { + plistener->setProgressStr (Glib::ustring::compose(M("TP_RAW_DMETHOD_PROGRESSBAR"), RAWParams::BayerSensor::getMethodString(RAWParams::BayerSensor::Method::HPHD))); + plistener->setProgress (0.0); + } + + JaggedArray hpmap (W, H, true); + +#ifdef _OPENMP + #pragma omp parallel + { + int tid = omp_get_thread_num(); + int nthreads = omp_get_num_threads(); + int blk = W / nthreads; + + if (tid < nthreads - 1) { + hphd_vertical (hpmap, tid * blk, (tid + 1)*blk); + } else { + hphd_vertical (hpmap, tid * blk, W); + } + } +#else + hphd_vertical (hpmap, 0, W); +#endif + + if (plistener) { + plistener->setProgress (0.33); + } + +#ifdef _OPENMP + #pragma omp parallel + { + int tid = omp_get_thread_num(); + int nthreads = omp_get_num_threads(); + int blk = H / nthreads; + + if (tid < nthreads - 1) { + hphd_horizontal (hpmap, tid * blk, (tid + 1)*blk); + } else { + hphd_horizontal (hpmap, tid * blk, H); + } + } +#else + hphd_horizontal (hpmap, 0, H); +#endif + + hphd_green (hpmap); + + if (plistener) { + plistener->setProgress (0.66); + } + + for (int i = 0; i < H; i++) { + if (i == 0) { + interpolate_row_rb_mul_pp (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 (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 (red[i], blue[i], green[i - 1], green[i], green[i + 1], i, 1.0, 1.0, 1.0, 0, W, 1); + } + } + + if (plistener) { + plistener->setProgress (1.0); + } +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +#define fc(row,col) (prefilters >> ((((row) << 1 & 14) + ((col) & 1)) << 1) & 3) +typedef unsigned short ushort; +void RawImageSource::vng4_demosaic () +{ + const signed short int *cp, terms[] = { + -2, -2, +0, -1, 0, 0x01, -2, -2, +0, +0, 1, 0x01, -2, -1, -1, +0, 0, 0x01, + -2, -1, +0, -1, 0, 0x02, -2, -1, +0, +0, 0, 0x03, -2, -1, +0, +1, 1, 0x01, + -2, +0, +0, -1, 0, 0x06, -2, +0, +0, +0, 1, 0x02, -2, +0, +0, +1, 0, 0x03, + -2, +1, -1, +0, 0, 0x04, -2, +1, +0, -1, 1, 0x04, -2, +1, +0, +0, 0, 0x06, + -2, +1, +0, +1, 0, 0x02, -2, +2, +0, +0, 1, 0x04, -2, +2, +0, +1, 0, 0x04, + -1, -2, -1, +0, 0, 0x80, -1, -2, +0, -1, 0, 0x01, -1, -2, +1, -1, 0, 0x01, + -1, -2, +1, +0, 1, 0x01, -1, -1, -1, +1, 0, 0x88, -1, -1, +1, -2, 0, 0x40, + -1, -1, +1, -1, 0, 0x22, -1, -1, +1, +0, 0, 0x33, -1, -1, +1, +1, 1, 0x11, + -1, +0, -1, +2, 0, 0x08, -1, +0, +0, -1, 0, 0x44, -1, +0, +0, +1, 0, 0x11, + -1, +0, +1, -2, 1, 0x40, -1, +0, +1, -1, 0, 0x66, -1, +0, +1, +0, 1, 0x22, + -1, +0, +1, +1, 0, 0x33, -1, +0, +1, +2, 1, 0x10, -1, +1, +1, -1, 1, 0x44, + -1, +1, +1, +0, 0, 0x66, -1, +1, +1, +1, 0, 0x22, -1, +1, +1, +2, 0, 0x10, + -1, +2, +0, +1, 0, 0x04, -1, +2, +1, +0, 1, 0x04, -1, +2, +1, +1, 0, 0x04, + +0, -2, +0, +0, 1, 0x80, +0, -1, +0, +1, 1, 0x88, +0, -1, +1, -2, 0, 0x40, + +0, -1, +1, +0, 0, 0x11, +0, -1, +2, -2, 0, 0x40, +0, -1, +2, -1, 0, 0x20, + +0, -1, +2, +0, 0, 0x30, +0, -1, +2, +1, 1, 0x10, +0, +0, +0, +2, 1, 0x08, + +0, +0, +2, -2, 1, 0x40, +0, +0, +2, -1, 0, 0x60, +0, +0, +2, +0, 1, 0x20, + +0, +0, +2, +1, 0, 0x30, +0, +0, +2, +2, 1, 0x10, +0, +1, +1, +0, 0, 0x44, + +0, +1, +1, +2, 0, 0x10, +0, +1, +2, -1, 1, 0x40, +0, +1, +2, +0, 0, 0x60, + +0, +1, +2, +1, 0, 0x20, +0, +1, +2, +2, 0, 0x10, +1, -2, +1, +0, 0, 0x80, + +1, -1, +1, +1, 0, 0x88, +1, +0, +1, +2, 0, 0x08, +1, +0, +2, -1, 0, 0x40, + +1, +0, +2, +1, 0, 0x10 + }, + chood[] = { -1, -1, -1, 0, -1, +1, 0, +1, +1, +1, +1, 0, +1, -1, 0, -1 }; + + double progress = 0.0; + const bool plistenerActive = plistener; + + if (plistenerActive) { + plistener->setProgressStr (Glib::ustring::compose(M("TP_RAW_DMETHOD_PROGRESSBAR"), RAWParams::BayerSensor::getMethodString(RAWParams::BayerSensor::Method::VNG4))); + plistener->setProgress (progress); + } + + const unsigned prefilters = ri->prefilters; + const int width = W, height = H; + constexpr unsigned int colors = 4; + float (*image)[4]; + + image = (float (*)[4]) calloc (height * width, sizeof * image); + +#ifdef _OPENMP + #pragma omp parallel for +#endif + + for (int ii = 0; ii < H; ii++) + for (int jj = 0; jj < W; jj++) { + image[ii * W + jj][fc(ii, jj)] = rawData[ii][jj]; + } + + { + int lcode[16][16][32]; + float mul[16][16][8]; + float csum[16][16][4]; + +// first linear interpolation + for (int row = 0; row < 16; row++) + for (int col = 0; col < 16; col++) { + int * ip = lcode[row][col]; + int mulcount = 0; + float sum[4]; + memset (sum, 0, sizeof sum); + + for (int y = -1; y <= 1; y++) + for (int x = -1; x <= 1; x++) { + int shift = (y == 0) + (x == 0); + + if (shift == 2) { + continue; + } + + int color = fc(row + y, col + x); + *ip++ = (width * y + x) * 4 + color; + + mul[row][col][mulcount] = (1 << shift); + *ip++ = color; + sum[color] += (1 << shift); + mulcount++; + } + + int colcount = 0; + + for (unsigned int c = 0; c < colors; c++) + if (c != fc(row, col)) { + *ip++ = c; + csum[row][col][colcount] = sum[c]; + colcount ++; + } + } + +StopWatch Stop1("loop 1"); +#ifdef _OPENMP + #pragma omp parallel for +#endif + + for (int row = 1; row < height - 1; row++) { + 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); + + 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]; + } + } + } +Stop1.stop(); + } + const int prow = 7, pcol = 1; + int *code[8][2]; + int t, g; + int * ip = (int *) calloc ((prow + 1) * (pcol + 1), 1280); + + for (int row = 0; row <= prow; row++) /* Precalculate for VNG */ + for (int col = 0; col <= pcol; col++) { + code[row][col] = ip; + + for (cp = terms, t = 0; t < 64; t++) { + int y1 = *cp++; + int x1 = *cp++; + int y2 = *cp++; + int x2 = *cp++; + int weight = *cp++; + int grads = *cp++; + unsigned int color = fc(row + y1, col + x1); + + if (fc(row + y2, col + x2) != color) { + continue; + } + + int diag = (fc(row, col + 1) == color && fc(row + 1, col) == color) ? 2 : 1; + + if (abs(y1 - y2) == diag && abs(x1 - x2) == diag) { + continue; + } + + *ip++ = (y1 * width + x1) * 4 + color; + *ip++ = (y2 * width + x2) * 4 + color; + *ip++ = weight; + + for (g = 0; g < 8; g++) + if (grads & (1 << g)) { + *ip++ = g; + } + + *ip++ = -1; + } + + *ip++ = INT_MAX; + + for (cp = chood, g = 0; g < 8; g++) { + int y = *cp++; + int x = *cp++; + *ip++ = (y * width + x) * 4; + unsigned int color = fc(row, col); + + if (fc(row + y, col + x) != color && fc(row + y * 2, col + x * 2) == color) { + *ip++ = (y * width + x) * 8 + color; + } else { + *ip++ = 0; + } + } + } + + if(plistenerActive) { + progress = 0.1; + plistener->setProgress (progress); + } + +StopWatch Stop2("loop 2"); + +#ifdef _OPENMP + #pragma omp parallel +#endif + { + float thold; + int g; + constexpr int progressStep = 64; + const double progressInc = (0.98 - progress) / ((height - 2) / progressStep); +#ifdef _OPENMP + #pragma omp for schedule(dynamic,16) nowait +#endif + + for (int row = 2; row < height - 2; row++) { /* Do VNG interpolation */ + for (int col = 2; col < width - 2; col++) { + float * pix = image[row * width + col]; + int * ip = code[row & prow][col & pcol]; + float gval[8] = {}; +// gval[0] = gval[1] = gval[2] = gval[3] = gval[4] = gval[5] = gval[6] = gval[7] = 0.f; +// memset (gval, 0, sizeof gval); + + while ((g = ip[0]) != INT_MAX) { /* Calculate gradients */ + float diff = fabsf(pix[g] - pix[ip[1]]) * (1 << ip[2]); + gval[ip[3]] += diff; + ip += 4; + + while ((g = *ip++) != -1) { + gval[g] += diff; + } + } + + ip++; + { + float gmin, gmax; + gmin = gmax = gval[0]; /* Choose a threshold */ + + for (g = 1; g < 8; g++) { + gmin = rtengine::min(gmin, gval[g]); +// if (gmin > gval[g]) { +// gmin = gval[g]; +// } + + gmax = rtengine::max(gmax, gval[g]); +// if (gmax < gval[g]) { +// gmax = gval[g]; +// } + } + + thold = gmin + (gmax / 2); + } + float sum[3] = {}; +// sum[0] = sum[1] = sum[2] = 0.f; +// memset (sum, 0, sizeof sum); + float t1, t2; + int color = fc(row, col); + t1 = t2 = pix[color]; + + if(color & 1) { + int num = 0; + + for (g = 0; g < 8; g++, ip += 2) { /* Average the neighbors */ + if (gval[g] <= thold) { + if(ip[1]) { + sum[0] += (t1 + pix[ip[1]]) * 0.5f; + } + + sum[1] += pix[ip[0] + (color ^ 2)]; + num++; + } + } + + t1 += (sum[1] - sum[0]) / num; + } else { + int num = 0; + + for (g = 0; g < 8; g++, ip += 2) { /* Average the neighbors */ + if (gval[g] <= thold) { + sum[1] += pix[ip[0] + 1]; + sum[2] += pix[ip[0] + 3]; + + if(ip[1]) { + sum[0] += (t1 + pix[ip[1]]) * 0.5f; + } + + num++; + } + } + + t1 += (sum[1] - sum[0]) / num; + t2 += (sum[2] - sum[0]) / num; + } + + green[row][col] = 0.5f * (t1 + t2); + } + + if(plistenerActive) { + if((row % progressStep) == 0) +#ifdef _OPENMP + #pragma omp critical (updateprogress) +#endif + { + progress += progressInc; + plistener->setProgress (progress); + } + } + } + + } +Stop2.stop(); + free (code[0][0]); + free (image); + + if(plistenerActive) { + plistener->setProgress (0.98); + } +StopWatch Stop3("loop 3"); + + // 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 (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 (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 (red[i], blue[i], green[i - 1], green[i], green[i + 1], i, 1.0, 1.0, 1.0, 0, W, 1); + } + } +Stop3.stop(); + if(plistenerActive) { + plistener->setProgress (1.0); + } +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +#undef fc +#define fc(row,col) \ + (ri->get_filters() >> ((((row) << 1 & 14) + ((col) & 1)) << 1) & 3) + +#define FORCC for (unsigned int c=0; c < colors; c++) + +/* + Patterned Pixel Grouping Interpolation by Alain Desbiolles +*/ +void RawImageSource::ppg_demosaic() +{ + int width = W, height = H; + int dir[5] = { 1, width, -1, -width, 1 }; + int row, col, diff[2] = {}, guess[2], c, d, i; + float (*pix)[4]; + + float (*image)[4]; + + if (plistener) { + // looks like ppg isn't supported anymore + //plistener->setProgressStr (Glib::ustring::compose(M("TP_RAW_DMETHOD_PROGRESSBAR"), RAWParams::BayerSensor::getMethodString(RAWParams::BayerSensor::ppg))); + plistener->setProgressStr (Glib::ustring::compose(M("TP_RAW_DMETHOD_PROGRESSBAR"), "xxx")); + plistener->setProgress (0.0); + } + + image = (float (*)[4]) calloc (H * W, sizeof * image); + + for (int ii = 0; ii < H; ii++) + for (int jj = 0; jj < W; jj++) { + image[ii * W + jj][fc(ii, jj)] = rawData[ii][jj]; + } + + border_interpolate(3, image); + + /* Fill in the green layer with gradients and pattern recognition: */ + for (row = 3; row < height - 3; row++) { + for (col = 3 + (FC(row, 3) & 1), c = FC(row, col); col < width - 3; col += 2) { + pix = image + row * width + col; + + for (i = 0; (d = dir[i]) > 0; i++) { + guess[i] = (pix[-d][1] + pix[0][c] + pix[d][1]) * 2 + - pix[-2 * d][c] - pix[2 * d][c]; + diff[i] = ( ABS(pix[-2 * d][c] - pix[ 0][c]) + + ABS(pix[ 2 * d][c] - pix[ 0][c]) + + ABS(pix[ -d][1] - pix[ d][1]) ) * 3 + + ( ABS(pix[ 3 * d][1] - pix[ d][1]) + + ABS(pix[-3 * d][1] - pix[-d][1]) ) * 2; + } + + d = dir[i = diff[0] > diff[1]]; + pix[0][1] = median(static_cast(guess[i] >> 2), pix[d][1], pix[-d][1]); + } + + if(plistener) { + plistener->setProgress(0.33 * row / (height - 3)); + } + } + + /* Calculate red and blue for each green pixel: */ + for (row = 1; row < height - 1; row++) { + for (col = 1 + (FC(row, 2) & 1), c = FC(row, col + 1); col < width - 1; col += 2) { + pix = image + row * width + col; + + for (i = 0; (d = dir[i]) > 0; c = 2 - c, i++) + pix[0][c] = CLIP(0.5 * (pix[-d][c] + pix[d][c] + 2 * pix[0][1] + - pix[-d][1] - pix[d][1]) ); + } + + if(plistener) { + plistener->setProgress(0.33 + 0.33 * row / (height - 1)); + } + } + + /* Calculate blue for red pixels and vice versa: */ + for (row = 1; row < height - 1; row++) { + for (col = 1 + (FC(row, 1) & 1), c = 2 - FC(row, col); col < width - 1; col += 2) { + pix = image + row * width + col; + + for (i = 0; (d = dir[i] + dir[i + 1]) > 0; i++) { + diff[i] = ABS(pix[-d][c] - pix[d][c]) + + ABS(pix[-d][1] - pix[0][1]) + + ABS(pix[ d][1] - pix[0][1]); + guess[i] = pix[-d][c] + pix[d][c] + 2 * pix[0][1] + - pix[-d][1] - pix[d][1]; + } + + if (diff[0] != diff[1]) { + pix[0][c] = CLIP(guess[diff[0] > diff[1]] / 2); + } else { + pix[0][c] = CLIP((guess[0] + guess[1]) / 4); + } + } + + if(plistener) { + plistener->setProgress(0.67 + 0.33 * row / (height - 1)); + } + } + + red(W, H); + + for (int i = 0; i < H; i++) + for (int j = 0; j < W; j++) { + red[i][j] = image[i * W + j][0]; + } + + green(W, H); + + for (int i = 0; i < H; i++) + for (int j = 0; j < W; j++) { + green[i][j] = image[i * W + j][1]; + } + + blue(W, H); + + for (int i = 0; i < H; i++) + for (int j = 0; j < W; j++) { + blue[i][j] = image[i * W + j][2]; + } + + free (image); +} + +void RawImageSource::border_interpolate(unsigned int border, float (*image)[4], unsigned int start, unsigned int end) +{ + unsigned row, col, y, x, f, sum[8]; + unsigned int width = W, height = H; + unsigned int colors = 3; + + if (end == 0 ) { + end = H; + } + + for (row = start; row < end; row++) + for (col = 0; col < width; col++) { + if (col == border && row >= border && row < height - border) { + col = width - border; + } + + memset (sum, 0, sizeof sum); + + for (y = row - 1; y != row + 2; y++) + for (x = col - 1; x != col + 2; x++) + if (y < height && x < width) { + f = fc(y, x); + sum[f] += image[y * width + x][f]; + sum[f + 4]++; + } + + f = fc(row, col); + + FORCC if (c != f && sum[c + 4]) { + image[row * width + col][c] = sum[c] / sum[c + 4]; + } + } +} + +void RawImageSource::border_interpolate2( int winw, int winh, int lborders) +{ + int bord = lborders; + int width = winw; + int height = winh; + + for (int i = 0; i < height; i++) { + + float sum[6]; + + for (int j = 0; j < bord; j++) { //first few columns + for (int c = 0; c < 6; c++) { + sum[c] = 0; + } + + for (int i1 = i - 1; i1 < i + 2; i1++) + for (int j1 = j - 1; j1 < j + 2; j1++) { + if ((i1 > -1) && (i1 < height) && (j1 > -1)) { + int c = FC(i1, j1); + sum[c] += rawData[i1][j1]; + sum[c + 3]++; + } + } + + int c = FC(i, j); + + if (c == 1) { + red[i][j] = sum[0] / sum[3]; + green[i][j] = rawData[i][j]; + blue[i][j] = sum[2] / sum[5]; + } else { + green[i][j] = sum[1] / sum[4]; + + if (c == 0) { + red[i][j] = rawData[i][j]; + blue[i][j] = sum[2] / sum[5]; + } else { + red[i][j] = sum[0] / sum[3]; + blue[i][j] = rawData[i][j]; + } + } + }//j + + for (int j = width - bord; j < width; j++) { //last few columns + for (int c = 0; c < 6; c++) { + sum[c] = 0; + } + + for (int i1 = i - 1; i1 < i + 2; i1++) + for (int j1 = j - 1; j1 < j + 2; j1++) { + if ((i1 > -1) && (i1 < height ) && (j1 < width)) { + int c = FC(i1, j1); + sum[c] += rawData[i1][j1]; + sum[c + 3]++; + } + } + + int c = FC(i, j); + + if (c == 1) { + red[i][j] = sum[0] / sum[3]; + green[i][j] = rawData[i][j]; + blue[i][j] = sum[2] / sum[5]; + } else { + green[i][j] = sum[1] / sum[4]; + + if (c == 0) { + red[i][j] = rawData[i][j]; + blue[i][j] = sum[2] / sum[5]; + } else { + red[i][j] = sum[0] / sum[3]; + blue[i][j] = rawData[i][j]; + } + } + }//j + }//i + + for (int i = 0; i < bord; i++) { + + float sum[6]; + + for (int j = bord; j < width - bord; j++) { //first few rows + for (int c = 0; c < 6; c++) { + sum[c] = 0; + } + + for (int i1 = i - 1; i1 < i + 2; i1++) + for (int j1 = j - 1; j1 < j + 2; j1++) { + if ((i1 > -1) && (i1 < height) && (j1 > -1)) { + int c = FC(i1, j1); + sum[c] += rawData[i1][j1]; + sum[c + 3]++; + } + } + + int c = FC(i, j); + + if (c == 1) { + red[i][j] = sum[0] / sum[3]; + green[i][j] = rawData[i][j]; + blue[i][j] = sum[2] / sum[5]; + } else { + green[i][j] = sum[1] / sum[4]; + + if (c == 0) { + red[i][j] = rawData[i][j]; + blue[i][j] = sum[2] / sum[5]; + } else { + red[i][j] = sum[0] / sum[3]; + blue[i][j] = rawData[i][j]; + } + } + }//j + } + + for (int i = height - bord; i < height; i++) { + + float sum[6]; + + for (int j = bord; j < width - bord; j++) { //last few rows + for (int c = 0; c < 6; c++) { + sum[c] = 0; + } + + for (int i1 = i - 1; i1 < i + 2; i1++) + for (int j1 = j - 1; j1 < j + 2; j1++) { + if ((i1 > -1) && (i1 < height) && (j1 < width)) { + int c = FC(i1, j1); + sum[c] += rawData[i1][j1]; + sum[c + 3]++; + } + } + + int c = FC(i, j); + + if (c == 1) { + red[i][j] = sum[0] / sum[3]; + green[i][j] = rawData[i][j]; + blue[i][j] = sum[2] / sum[5]; + } else { + green[i][j] = sum[1] / sum[4]; + + if (c == 0) { + red[i][j] = rawData[i][j]; + blue[i][j] = sum[2] / sum[5]; + } else { + red[i][j] = sum[0] / sum[3]; + blue[i][j] = rawData[i][j]; + } + } + }//j + } + +} + +// Joint Demosaicing and Denoising using High Order Interpolation Techniques +// Revision 0.9.1a - 09/02/2010 - Contact info: luis.sanz.rodriguez@gmail.com +// Copyright Luis Sanz Rodriguez 2010 +// Adapted to RawTherapee by Jacques Desmis 3/2013 + +void RawImageSource::jdl_interpolate_omp() // from "Lassus" +{ + int width = W, height = H; + int row, col, c, d, i, u = width, v = 2 * u, w = 3 * u, x = 4 * u, y = 5 * u, z = 6 * u, indx, (*dif)[2], (*chr)[2]; + float f[4], g[4]; + float (*image)[4]; + image = (float (*)[4]) calloc (width * height, sizeof * image); + dif = (int (*)[2]) calloc(width * height, sizeof * dif); + chr = (int (*)[2]) calloc(width * height, sizeof * chr); + + if (plistener) { + // this function seems to be unused + //plistener->setProgressStr (Glib::ustring::compose(M("TP_RAW_DMETHOD_PROGRESSBAR"), RAWParams::BayerSensor::getMethodString(RAWParams::BayerSensor::jdl))); + plistener->setProgressStr (Glib::ustring::compose(M("TP_RAW_DMETHOD_PROGRESSBAR"), "xxx")); + plistener->setProgress (0.0); + } + +#ifdef _OPENMP + #pragma omp parallel default(none) shared(image,width,height,u,w,v,y,x,z,dif,chr) private(row,col,f,g,indx,c,d,i) +#endif + { +#ifdef _OPENMP + #pragma omp for +#endif + + for (int ii = 0; ii < height; ii++) + for (int jj = 0; jj < width; jj++) { + image[ii * width + jj][fc(ii, jj)] = rawData[ii][jj]; + } + + border_interpolate(6, image); + +#ifdef _OPENMP + #pragma omp for +#endif + + for (row = 5; row < height - 5; row++) + for (col = 5 + (FC(row, 1) & 1), indx = row * width + col, c = FC(row, col); col < u - 5; col += 2, indx += 2) { + f[0] = 1.f + abs(image[indx - u][1] - image[indx - w][1]) + abs(image[indx - u][1] - image[indx + u][1]) + abs(image[indx][c] - image[indx - v][c]) + abs(image[indx - v][c] - image[indx - x][c]); + f[1] = 1.f + abs(image[indx + 1][1] - image[indx + 3][1]) + abs(image[indx + 1][1] - image[indx - 1][1]) + abs(image[indx][c] - image[indx + 2][c]) + abs(image[indx + 2][c] - image[indx + 4][c]); + f[2] = 1.f + abs(image[indx - 1][1] - image[indx - 3][1]) + abs(image[indx - 1][1] - image[indx + 1][1]) + abs(image[indx][c] - image[indx - 2][c]) + abs(image[indx - 2][c] - image[indx - 4][c]); + f[3] = 1.f + abs(image[indx + u][1] - image[indx + w][1]) + abs(image[indx + u][1] - image[indx - u][1]) + abs(image[indx][c] - image[indx + v][c]) + abs(image[indx + v][c] - image[indx + x][c]); + g[0] = CLIP((22.f * image[indx - u][1] + 22.f * image[indx - w][1] + 2.f * image[indx - y][1] + 2.f * image[indx + u][1] + 40.f * image[indx][c] - 32.f * image[indx - v][c] - 8.f * image[indx - x][c]) / 48.f); + g[1] = CLIP((22.f * image[indx + 1][1] + 22.f * image[indx + 3][1] + 2.f * image[indx + 5][1] + 2.f * image[indx - 1][1] + 40.f * image[indx][c] - 32.f * image[indx + 2][c] - 8.f * image[indx + 4][c]) / 48.f); + g[2] = CLIP((22.f * image[indx - 1][1] + 22.f * image[indx - 3][1] + 2.f * image[indx - 5][1] + 2.f * image[indx + 1][1] + 40.f * image[indx][c] - 32.f * image[indx - 2][c] - 8.f * image[indx - 4][c]) / 48.f); + g[3] = CLIP((22.f * image[indx + u][1] + 22.f * image[indx + w][1] + 2.f * image[indx + y][1] + 2.f * image[indx - u][1] + 40.f * image[indx][c] - 32.f * image[indx + v][c] - 8.f * image[indx + x][c]) / 48.f); + dif[indx][0] = CLIP((f[3] * g[0] + f[0] * g[3]) / (f[0] + f[3])) - image[indx][c]; + dif[indx][1] = CLIP((f[2] * g[1] + f[1] * g[2]) / (f[1] + f[2])) - image[indx][c]; + } + +#ifdef _OPENMP + #pragma omp for +#endif + + for (row = 6; row < height - 6; row++) + for (col = 6 + (FC(row, 2) & 1), indx = row * width + col, c = FC(row, col) / 2; col < u - 6; col += 2, indx += 2) { + f[0] = 1.f + 78.f * SQR((float)dif[indx][0]) + 69.f * (SQR((float) dif[indx - v][0]) + SQR((float)dif[indx + v][0])) + 51.f * (SQR((float)dif[indx - x][0]) + SQR((float)dif[indx + x][0])) + 21.f * (SQR((float)dif[indx - z][0]) + SQR((float)dif[indx + z][0])) - 6.f * SQR((float)dif[indx - v][0] + dif[indx][0] + dif[indx + v][0]) - 10.f * (SQR((float)dif[indx - x][0] + dif[indx - v][0] + dif[indx][0]) + SQR((float)dif[indx][0] + dif[indx + v][0] + dif[indx + x][0])) - 7.f * (SQR((float)dif[indx - z][0] + dif[indx - x][0] + dif[indx - v][0]) + SQR((float)dif[indx + v][0] + dif[indx + x][0] + dif[indx + z][0])); + f[1] = 1.f + 78.f * SQR((float)dif[indx][1]) + 69.f * (SQR((float)dif[indx - 2][1]) + SQR((float)dif[indx + 2][1])) + 51.f * (SQR((float)dif[indx - 4][1]) + SQR((float)dif[indx + 4][1])) + 21.f * (SQR((float)dif[indx - 6][1]) + SQR((float)dif[indx + 6][1])) - 6.f * SQR((float)dif[indx - 2][1] + dif[indx][1] + dif[indx + 2][1]) - 10.f * (SQR((float)dif[indx - 4][1] + dif[indx - 2][1] + dif[indx][1]) + SQR((float)dif[indx][1] + dif[indx + 2][1] + dif[indx + 4][1])) - 7.f * (SQR((float)dif[indx - 6][1] + dif[indx - 4][1] + dif[indx - 2][1]) + SQR((float)dif[indx + 2][1] + dif[indx + 4][1] + dif[indx + 6][1])); + g[0] = median(0.725f * dif[indx][0] + 0.1375f * dif[indx - v][0] + 0.1375f * dif[indx + v][0], static_cast(dif[indx - v][0]), static_cast(dif[indx + v][0])); + g[1] = median(0.725f * dif[indx][1] + 0.1375f * dif[indx - 2][1] + 0.1375f * dif[indx + 2][1], static_cast(dif[indx - 2][1]), static_cast(dif[indx + 2][1])); + chr[indx][c] = (f[1] * g[0] + f[0] * g[1]) / (f[0] + f[1]); + } + +#ifdef _OPENMP + #pragma omp for +#endif + + for (row = 6; row < height - 6; row++) + for (col = 6 + (FC(row, 2) & 1), indx = row * width + col, c = 1 - FC(row, col) / 2, d = 2 * c; col < u - 6; col += 2, indx += 2) { + f[0] = 1.f / (float)(1.f + fabs((float)chr[indx - u - 1][c] - chr[indx + u + 1][c]) + fabs((float)chr[indx - u - 1][c] - chr[indx - w - 3][c]) + fabs((float)chr[indx + u + 1][c] - chr[indx - w - 3][c])); + f[1] = 1.f / (float)(1.f + fabs((float)chr[indx - u + 1][c] - chr[indx + u - 1][c]) + fabs((float)chr[indx - u + 1][c] - chr[indx - w + 3][c]) + fabs((float)chr[indx + u - 1][c] - chr[indx - w + 3][c])); + f[2] = 1.f / (float)(1.f + fabs((float)chr[indx + u - 1][c] - chr[indx - u + 1][c]) + fabs((float)chr[indx + u - 1][c] - chr[indx + w + 3][c]) + fabs((float)chr[indx - u + 1][c] - chr[indx + w - 3][c])); + f[3] = 1.f / (float)(1.f + fabs((float)chr[indx + u + 1][c] - chr[indx - u - 1][c]) + fabs((float)chr[indx + u + 1][c] - chr[indx + w - 3][c]) + fabs((float)chr[indx - u - 1][c] - chr[indx + w + 3][c])); + g[0] = median(chr[indx - u - 1][c], chr[indx - w - 1][c], chr[indx - u - 3][c]); + g[1] = median(chr[indx - u + 1][c], chr[indx - w + 1][c], chr[indx - u + 3][c]); + g[2] = median(chr[indx + u - 1][c], chr[indx + w - 1][c], chr[indx + u - 3][c]); + g[3] = median(chr[indx + u + 1][c], chr[indx + w + 1][c], chr[indx + u + 3][c]); + chr[indx][c] = (f[0] * g[0] + f[1] * g[1] + f[2] * g[2] + f[3] * g[3]) / (f[0] + f[1] + f[2] + f[3]); + image[indx][1] = CLIP(image[indx][2 - d] + chr[indx][1 - c]); + image[indx][d] = CLIP(image[indx][1] - chr[indx][c]); + } + +#ifdef _OPENMP + #pragma omp for +#endif + + for (row = 6; row < height - 6; row++) + for (col = 6 + (FC(row, 1) & 1), indx = row * width + col, c = FC(row, col + 1) / 2, d = 2 * c; col < u - 6; col += 2, indx += 2) + for(i = 0; i <= 1; c = 1 - c, d = 2 * c, i++) { + f[0] = 1.f / (float)(1.f + fabs((float)chr[indx - u][c] - chr[indx + u][c]) + fabs((float)chr[indx - u][c] - chr[indx - w][c]) + fabs((float)chr[indx + u][c] - chr[indx - w][c])); + f[1] = 1.f / (float)(1.f + fabs((float)chr[indx + 1][c] - chr[indx - 1][c]) + fabs((float)chr[indx + 1][c] - chr[indx + 3][c]) + fabs((float)chr[indx - 1][c] - chr[indx + 3][c])); + f[2] = 1.f / (float)(1.f + fabs((float)chr[indx - 1][c] - chr[indx + 1][c]) + fabs((float)chr[indx - 1][c] - chr[indx - 3][c]) + fabs((float)chr[indx + 1][c] - chr[indx - 3][c])); + f[3] = 1.f / (float)(1.f + fabs((float)chr[indx + u][c] - chr[indx - u][c]) + fabs((float)chr[indx + u][c] - chr[indx + w][c]) + fabs((float)chr[indx - u][c] - chr[indx + w][c])); + g[0] = 0.875f * chr[indx - u][c] + 0.125f * chr[indx - w][c]; + g[1] = 0.875f * chr[indx + 1][c] + 0.125f * chr[indx + 3][c]; + g[2] = 0.875f * chr[indx - 1][c] + 0.125f * chr[indx - 3][c]; + g[3] = 0.875f * chr[indx + u][c] + 0.125f * chr[indx + w][c]; + image[indx][d] = CLIP(image[indx][1] - (f[0] * g[0] + f[1] * g[1] + f[2] * g[2] + f[3] * g[3]) / (f[0] + f[1] + f[2] + f[3])); + } + +#ifdef _OPENMP + #pragma omp for +#endif + + for (int ii = 0; ii < height; ii++) { + for (int jj = 0; jj < width; jj++) { + red[ii][jj] = CLIP(image[ii * width + jj][0]); + green[ii][jj] = CLIP(image[ii * width + jj][1]); + blue[ii][jj] = CLIP(image[ii * width + jj][2]); + } + } + } // End of parallelization + free (image); + free(dif); + free(chr); + //RawImageSource::refinement_lassus(); +} + +// LSMME demosaicing algorithm +// L. Zhang and X. Wu, +// Color demozaicing via directional Linear Minimum Mean Square-error Estimation, +// IEEE Trans. on Image Processing, vol. 14, pp. 2167-2178, +// Dec. 2005. +// Adapted to RawTherapee by Jacques Desmis 3/2013 +// Improved speed and reduced memory consumption by Ingo Weyrich 2/2015 +//TODO Tiles to reduce memory consumption +void RawImageSource::lmmse_interpolate_omp(int winw, int winh, array2D &rawData, array2D &red, array2D &green, array2D &blue, int iterations) +{ + const int width = winw, height = winh; + const int ba = 10; + const int rr1 = height + 2 * ba; + const int cc1 = width + 2 * ba; + const int w1 = cc1; + const int w2 = 2 * w1; + const int w3 = 3 * w1; + const int w4 = 4 * w1; + float h0, h1, h2, h3, h4, hs; + h0 = 1.0f; + h1 = exp( -1.0f / 8.0f); + h2 = exp( -4.0f / 8.0f); + h3 = exp( -9.0f / 8.0f); + h4 = exp(-16.0f / 8.0f); + hs = h0 + 2.0f * (h1 + h2 + h3 + h4); + h0 /= hs; + h1 /= hs; + h2 /= hs; + h3 /= hs; + h4 /= hs; + int passref = 0; + int iter = 0; + + if(iterations <= 4) { + iter = iterations - 1; + passref = 0; + } else if (iterations <= 6) { + iter = 3; + passref = iterations - 4; + } else if (iterations <= 8) { + iter = 3; + passref = iterations - 6; + } + + bool applyGamma = true; + + if(iterations == 0) { + applyGamma = false; + iter = 0; + } else { + applyGamma = true; + } + + float *rix[5]; + float *qix[5]; + float *buffer = (float *)calloc(rr1 * cc1 * 5 * sizeof(float), 1); + + if(buffer == nullptr) { // allocation of big block of memory failed, try to get 5 smaller ones + printf("lmmse_interpolate_omp: allocation of big memory block failed, try to get 5 smaller ones now...\n"); + bool allocationFailed = false; + + for(int i = 0; i < 5; i++) { + qix[i] = (float *)calloc(rr1 * cc1 * sizeof(float), 1); + + if(!qix[i]) { // allocation of at least one small block failed + allocationFailed = true; + } + } + + if(allocationFailed) { // fall back to igv_interpolate + printf("lmmse_interpolate_omp: allocation of 5 small memory blocks failed, falling back to igv_interpolate...\n"); + + for(int i = 0; i < 5; i++) { // free the already allocated buffers + if(qix[i]) { + free(qix[i]); + } + } + + igv_interpolate(winw, winh); + return; + } + } else { + qix[0] = buffer; + + for(int i = 1; i < 5; i++) { + qix[i] = qix[i - 1] + rr1 * cc1; + } + } + + if (plistener) { + plistener->setProgressStr (Glib::ustring::compose(M("TP_RAW_DMETHOD_PROGRESSBAR"), RAWParams::BayerSensor::getMethodString(RAWParams::BayerSensor::Method::LMMSE))); + plistener->setProgress (0.0); + } + + + LUTf *gamtab; + + if(applyGamma) { + gamtab = &(Color::gammatab_24_17a); + } else { + gamtab = new LUTf(65536, LUT_CLIP_ABOVE | LUT_CLIP_BELOW); + gamtab->makeIdentity(65535.f); + } + + +#ifdef _OPENMP + #pragma omp parallel private(rix) +#endif + { +#ifdef _OPENMP + #pragma omp for +#endif + + for (int rrr = ba; rrr < rr1 - ba; rrr++) { + for (int ccc = ba, row = rrr - ba; ccc < cc1 - ba; ccc++) { + int col = ccc - ba; + float *rix = qix[4] + rrr * cc1 + ccc; + rix[0] = (*gamtab)[rawData[row][col]]; + } + } + +#ifdef _OPENMP + #pragma omp single +#endif + { + if (plistener) { + plistener->setProgress (0.1); + } + } + + // G-R(B) +#ifdef _OPENMP + #pragma omp for schedule(dynamic,16) +#endif + + for (int rr = 2; rr < rr1 - 2; rr++) { + // G-R(B) at R(B) location + for (int cc = 2 + (FC(rr, 2) & 1); cc < cc1 - 2; cc += 2) { + rix[4] = qix[4] + rr * cc1 + cc; + float v0 = x00625(rix[4][-w1 - 1] + rix[4][-w1 + 1] + rix[4][w1 - 1] + rix[4][w1 + 1]) + x0250(rix[4][0]); + // horizontal + rix[0] = qix[0] + rr * cc1 + cc; + rix[0][0] = - x0250(rix[4][ -2] + rix[4][ 2]) + xdiv2f(rix[4][ -1] + rix[4][0] + rix[4][ 1]); + float Y = v0 + xdiv2f(rix[0][0]); + + if (rix[4][0] > 1.75f * Y) { + rix[0][0] = median(rix[0][0], rix[4][ -1], rix[4][ 1]); + } else { + rix[0][0] = LIM(rix[0][0], 0.0f, 1.0f); + } + + rix[0][0] -= rix[4][0]; + // vertical + rix[1] = qix[1] + rr * cc1 + cc; + rix[1][0] = -x0250(rix[4][-w2] + rix[4][w2]) + xdiv2f(rix[4][-w1] + rix[4][0] + rix[4][w1]); + Y = v0 + xdiv2f(rix[1][0]); + + if (rix[4][0] > 1.75f * Y) { + rix[1][0] = median(rix[1][0], rix[4][-w1], rix[4][w1]); + } else { + rix[1][0] = LIM(rix[1][0], 0.0f, 1.0f); + } + + rix[1][0] -= rix[4][0]; + } + + // G-R(B) at G location + for (int ccc = 2 + (FC(rr, 3) & 1); ccc < cc1 - 2; ccc += 2) { + rix[0] = qix[0] + rr * cc1 + ccc; + rix[1] = qix[1] + rr * cc1 + ccc; + rix[4] = qix[4] + rr * cc1 + ccc; + rix[0][0] = x0250(rix[4][ -2] + rix[4][ 2]) - xdiv2f(rix[4][ -1] + rix[4][0] + rix[4][ 1]); + rix[1][0] = x0250(rix[4][-w2] + rix[4][w2]) - xdiv2f(rix[4][-w1] + rix[4][0] + rix[4][w1]); + rix[0][0] = LIM(rix[0][0], -1.0f, 0.0f) + rix[4][0]; + rix[1][0] = LIM(rix[1][0], -1.0f, 0.0f) + rix[4][0]; + } + } + +#ifdef _OPENMP + #pragma omp single +#endif + { + if (plistener) { + plistener->setProgress (0.2); + } + } + + + // apply low pass filter on differential colors +#ifdef _OPENMP + #pragma omp for +#endif + + for (int rr = 4; rr < rr1 - 4; rr++) + for (int cc = 4; cc < cc1 - 4; cc++) { + rix[0] = qix[0] + rr * cc1 + cc; + rix[2] = qix[2] + rr * cc1 + cc; + rix[2][0] = h0 * rix[0][0] + h1 * (rix[0][ -1] + rix[0][ 1]) + h2 * (rix[0][ -2] + rix[0][ 2]) + h3 * (rix[0][ -3] + rix[0][ 3]) + h4 * (rix[0][ -4] + rix[0][ 4]); + rix[1] = qix[1] + rr * cc1 + cc; + rix[3] = qix[3] + rr * cc1 + cc; + rix[3][0] = h0 * rix[1][0] + h1 * (rix[1][-w1] + rix[1][w1]) + h2 * (rix[1][-w2] + rix[1][w2]) + h3 * (rix[1][-w3] + rix[1][w3]) + h4 * (rix[1][-w4] + rix[1][w4]); + } + +#ifdef _OPENMP + #pragma omp single +#endif + { + if (plistener) { + plistener->setProgress (0.3); + } + } + + // interpolate G-R(B) at R(B) +#ifdef _OPENMP + #pragma omp for +#endif + + for (int rr = 4; rr < rr1 - 4; rr++) { + int cc = 4 + (FC(rr, 4) & 1); +#ifdef __SSE2__ + __m128 p1v, p2v, p3v, p4v, p5v, p6v, p7v, p8v, p9v, muv, vxv, vnv, xhv, vhv, xvv, vvv; + __m128 epsv = _mm_set1_ps(1e-7); + __m128 ninev = _mm_set1_ps(9.f); + + for (; cc < cc1 - 10; cc += 8) { + rix[0] = qix[0] + rr * cc1 + cc; + rix[1] = qix[1] + rr * cc1 + cc; + rix[2] = qix[2] + rr * cc1 + cc; + rix[3] = qix[3] + rr * cc1 + cc; + rix[4] = qix[4] + rr * cc1 + cc; + // horizontal + p1v = LC2VFU(rix[2][-4]); + p2v = LC2VFU(rix[2][-3]); + p3v = LC2VFU(rix[2][-2]); + p4v = LC2VFU(rix[2][-1]); + p5v = LC2VFU(rix[2][ 0]); + p6v = LC2VFU(rix[2][ 1]); + p7v = LC2VFU(rix[2][ 2]); + p8v = LC2VFU(rix[2][ 3]); + p9v = LC2VFU(rix[2][ 4]); + muv = (p1v + p2v + p3v + p4v + p5v + p6v + p7v + p8v + p9v) / ninev; + vxv = epsv + SQRV(p1v - muv) + SQRV(p2v - muv) + SQRV(p3v - muv) + SQRV(p4v - muv) + SQRV(p5v - muv) + SQRV(p6v - muv) + SQRV(p7v - muv) + SQRV(p8v - muv) + SQRV(p9v - muv); + p1v -= LC2VFU(rix[0][-4]); + p2v -= LC2VFU(rix[0][-3]); + p3v -= LC2VFU(rix[0][-2]); + p4v -= LC2VFU(rix[0][-1]); + p5v -= LC2VFU(rix[0][ 0]); + p6v -= LC2VFU(rix[0][ 1]); + p7v -= LC2VFU(rix[0][ 2]); + p8v -= LC2VFU(rix[0][ 3]); + p9v -= LC2VFU(rix[0][ 4]); + vnv = epsv + SQRV(p1v) + SQRV(p2v) + SQRV(p3v) + SQRV(p4v) + SQRV(p5v) + SQRV(p6v) + SQRV(p7v) + SQRV(p8v) + SQRV(p9v); + xhv = (LC2VFU(rix[0][0]) * vxv + LC2VFU(rix[2][0]) * vnv) / (vxv + vnv); + vhv = vxv * vnv / (vxv + vnv); + + // vertical + p1v = LC2VFU(rix[3][-w4]); + p2v = LC2VFU(rix[3][-w3]); + p3v = LC2VFU(rix[3][-w2]); + p4v = LC2VFU(rix[3][-w1]); + p5v = LC2VFU(rix[3][ 0]); + p6v = LC2VFU(rix[3][ w1]); + p7v = LC2VFU(rix[3][ w2]); + p8v = LC2VFU(rix[3][ w3]); + p9v = LC2VFU(rix[3][ w4]); + muv = (p1v + p2v + p3v + p4v + p5v + p6v + p7v + p8v + p9v) / ninev; + vxv = epsv + SQRV(p1v - muv) + SQRV(p2v - muv) + SQRV(p3v - muv) + SQRV(p4v - muv) + SQRV(p5v - muv) + SQRV(p6v - muv) + SQRV(p7v - muv) + SQRV(p8v - muv) + SQRV(p9v - muv); + p1v -= LC2VFU(rix[1][-w4]); + p2v -= LC2VFU(rix[1][-w3]); + p3v -= LC2VFU(rix[1][-w2]); + p4v -= LC2VFU(rix[1][-w1]); + p5v -= LC2VFU(rix[1][ 0]); + p6v -= LC2VFU(rix[1][ w1]); + p7v -= LC2VFU(rix[1][ w2]); + p8v -= LC2VFU(rix[1][ w3]); + p9v -= LC2VFU(rix[1][ w4]); + vnv = epsv + SQRV(p1v) + SQRV(p2v) + SQRV(p3v) + SQRV(p4v) + SQRV(p5v) + SQRV(p6v) + SQRV(p7v) + SQRV(p8v) + SQRV(p9v); + xvv = (LC2VFU(rix[1][0]) * vxv + LC2VFU(rix[3][0]) * vnv) / (vxv + vnv); + vvv = vxv * vnv / (vxv + vnv); + // interpolated G-R(B) + muv = (xhv * vvv + xvv * vhv) / (vhv + vvv); + STC2VFU(rix[4][0], muv); + } + +#endif + + for (; cc < cc1 - 4; cc += 2) { + rix[0] = qix[0] + rr * cc1 + cc; + rix[1] = qix[1] + rr * cc1 + cc; + rix[2] = qix[2] + rr * cc1 + cc; + rix[3] = qix[3] + rr * cc1 + cc; + rix[4] = qix[4] + rr * cc1 + cc; + // horizontal + float p1 = rix[2][-4]; + float p2 = rix[2][-3]; + float p3 = rix[2][-2]; + float p4 = rix[2][-1]; + float p5 = rix[2][ 0]; + float p6 = rix[2][ 1]; + float p7 = rix[2][ 2]; + float p8 = rix[2][ 3]; + float p9 = rix[2][ 4]; + float mu = (p1 + p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9) / 9.f; + float vx = 1e-7 + SQR(p1 - mu) + SQR(p2 - mu) + SQR(p3 - mu) + SQR(p4 - mu) + SQR(p5 - mu) + SQR(p6 - mu) + SQR(p7 - mu) + SQR(p8 - mu) + SQR(p9 - mu); + p1 -= rix[0][-4]; + p2 -= rix[0][-3]; + p3 -= rix[0][-2]; + p4 -= rix[0][-1]; + p5 -= rix[0][ 0]; + p6 -= rix[0][ 1]; + p7 -= rix[0][ 2]; + p8 -= rix[0][ 3]; + p9 -= rix[0][ 4]; + float vn = 1e-7 + SQR(p1) + SQR(p2) + SQR(p3) + SQR(p4) + SQR(p5) + SQR(p6) + SQR(p7) + SQR(p8) + SQR(p9); + float xh = (rix[0][0] * vx + rix[2][0] * vn) / (vx + vn); + float vh = vx * vn / (vx + vn); + + // vertical + p1 = rix[3][-w4]; + p2 = rix[3][-w3]; + p3 = rix[3][-w2]; + p4 = rix[3][-w1]; + p5 = rix[3][ 0]; + p6 = rix[3][ w1]; + p7 = rix[3][ w2]; + p8 = rix[3][ w3]; + p9 = rix[3][ w4]; + mu = (p1 + p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9) / 9.f; + vx = 1e-7 + SQR(p1 - mu) + SQR(p2 - mu) + SQR(p3 - mu) + SQR(p4 - mu) + SQR(p5 - mu) + SQR(p6 - mu) + SQR(p7 - mu) + SQR(p8 - mu) + SQR(p9 - mu); + p1 -= rix[1][-w4]; + p2 -= rix[1][-w3]; + p3 -= rix[1][-w2]; + p4 -= rix[1][-w1]; + p5 -= rix[1][ 0]; + p6 -= rix[1][ w1]; + p7 -= rix[1][ w2]; + p8 -= rix[1][ w3]; + p9 -= rix[1][ w4]; + vn = 1e-7 + SQR(p1) + SQR(p2) + SQR(p3) + SQR(p4) + SQR(p5) + SQR(p6) + SQR(p7) + SQR(p8) + SQR(p9); + float xv = (rix[1][0] * vx + rix[3][0] * vn) / (vx + vn); + float vv = vx * vn / (vx + vn); + // interpolated G-R(B) + rix[4][0] = (xh * vv + xv * vh) / (vh + vv); + } + } + +#ifdef _OPENMP + #pragma omp single +#endif + { + if (plistener) { + plistener->setProgress (0.4); + } + } + + // copy CFA values +#ifdef _OPENMP + #pragma omp for +#endif + + for (int rr = 0; rr < rr1; rr++) + for (int cc = 0, row = rr - ba; cc < cc1; cc++) { + int col = cc - ba; + int c = FC(rr, cc); + rix[c] = qix[c] + rr * cc1 + cc; + + if ((row >= 0) & (row < height) & (col >= 0) & (col < width)) { + rix[c][0] = (*gamtab)[rawData[row][col]]; + } else { + rix[c][0] = 0.f; + } + + if (c != 1) { + rix[1] = qix[1] + rr * cc1 + cc; + rix[4] = qix[4] + rr * cc1 + cc; + rix[1][0] = rix[c][0] + rix[4][0]; + } + } + +#ifdef _OPENMP + #pragma omp single +#endif + { + if (plistener) { + plistener->setProgress (0.5); + } + } + + // bilinear interpolation for R/B + // interpolate R/B at G location +#ifdef _OPENMP + #pragma omp for +#endif + + for (int rr = 1; rr < rr1 - 1; rr++) + for (int cc = 1 + (FC(rr, 2) & 1), c = FC(rr, cc + 1); cc < cc1 - 1; cc += 2) { + rix[c] = qix[c] + rr * cc1 + cc; + rix[1] = qix[1] + rr * cc1 + cc; + rix[c][0] = rix[1][0] + xdiv2f(rix[c][ -1] - rix[1][ -1] + rix[c][ 1] - rix[1][ 1]); + c = 2 - c; + rix[c] = qix[c] + rr * cc1 + cc; + rix[c][0] = rix[1][0] + xdiv2f(rix[c][-w1] - rix[1][-w1] + rix[c][w1] - rix[1][w1]); + c = 2 - c; + } + +#ifdef _OPENMP + #pragma omp single +#endif + { + if (plistener) { + plistener->setProgress (0.6); + } + } + + // interpolate R/B at B/R location +#ifdef _OPENMP + #pragma omp for +#endif + + for (int rr = 1; rr < rr1 - 1; rr++) + for (int cc = 1 + (FC(rr, 1) & 1), c = 2 - FC(rr, cc); cc < cc1 - 1; cc += 2) { + rix[c] = qix[c] + rr * cc1 + cc; + rix[1] = qix[1] + rr * cc1 + cc; + rix[c][0] = rix[1][0] + x0250(rix[c][-w1] - rix[1][-w1] + rix[c][ -1] - rix[1][ -1] + rix[c][ 1] - rix[1][ 1] + rix[c][ w1] - rix[1][ w1]); + } + +#ifdef _OPENMP + #pragma omp single +#endif + { + if (plistener) { + plistener->setProgress (0.7); + } + } + + }// End of parallelization 1 + + // median filter/ + for (int pass = 0; pass < iter; pass++) { + // Apply 3x3 median filter + // Compute median(R-G) and median(B-G) + +#ifdef _OPENMP + #pragma omp parallel for private(rix) +#endif + + for (int rr = 1; rr < rr1 - 1; rr++) { + for (int c = 0; c < 3; c += 2) { + int d = c + 3 - (c == 0 ? 0 : 1); + int cc = 1; +#ifdef __SSE2__ + + for (; cc < cc1 - 4; cc += 4) { + rix[d] = qix[d] + rr * cc1 + cc; + rix[c] = qix[c] + rr * cc1 + cc; + rix[1] = qix[1] + rr * cc1 + cc; + // Assign 3x3 differential color values + const std::array p = { + LVFU(rix[c][-w1 - 1]) - LVFU(rix[1][-w1 - 1]), + LVFU(rix[c][-w1]) - LVFU(rix[1][-w1]), + LVFU(rix[c][-w1 + 1]) - LVFU(rix[1][-w1 + 1]), + LVFU(rix[c][ -1]) - LVFU(rix[1][ -1]), + LVFU(rix[c][ 0]) - LVFU(rix[1][ 0]), + LVFU(rix[c][ 1]) - LVFU(rix[1][ 1]), + LVFU(rix[c][ w1 - 1]) - LVFU(rix[1][ w1 - 1]), + LVFU(rix[c][ w1]) - LVFU(rix[1][ w1]), + LVFU(rix[c][ w1 + 1]) - LVFU(rix[1][ w1 + 1]) + }; + _mm_storeu_ps(&rix[d][0], median(p)); + } + +#endif + + for (; cc < cc1 - 1; cc++) { + rix[d] = qix[d] + rr * cc1 + cc; + rix[c] = qix[c] + rr * cc1 + cc; + rix[1] = qix[1] + rr * cc1 + cc; + // Assign 3x3 differential color values + const std::array p = { + rix[c][-w1 - 1] - rix[1][-w1 - 1], + rix[c][-w1] - rix[1][-w1], + rix[c][-w1 + 1] - rix[1][-w1 + 1], + rix[c][ -1] - rix[1][ -1], + rix[c][ 0] - rix[1][ 0], + rix[c][ 1] - rix[1][ 1], + rix[c][ w1 - 1] - rix[1][ w1 - 1], + rix[c][ w1] - rix[1][ w1], + rix[c][ w1 + 1] - rix[1][ w1 + 1] + }; + rix[d][0] = median(p); + } + } + } + + // red/blue at GREEN pixel locations & red/blue and green at BLUE/RED pixel locations +#ifdef _OPENMP + #pragma omp parallel for private (rix) +#endif + + for (int rr = 0; rr < rr1; rr++) { + rix[0] = qix[0] + rr * cc1; + rix[1] = qix[1] + rr * cc1; + rix[2] = qix[2] + rr * cc1; + rix[3] = qix[3] + rr * cc1; + rix[4] = qix[4] + rr * cc1; + int c0 = FC(rr, 0); + int c1 = FC(rr, 1); + + if(c0 == 1) { + c1 = 2 - c1; + int d = c1 + 3 - (c1 == 0 ? 0 : 1); + int cc; + + for (cc = 0; cc < cc1 - 1; cc += 2) { + rix[0][0] = rix[1][0] + rix[3][0]; + rix[2][0] = rix[1][0] + rix[4][0]; + rix[0]++; + rix[1]++; + rix[2]++; + rix[3]++; + rix[4]++; + rix[c1][0] = rix[1][0] + rix[d][0]; + rix[1][0] = 0.5f * (rix[0][0] - rix[3][0] + rix[2][0] - rix[4][0]); + rix[0]++; + rix[1]++; + rix[2]++; + rix[3]++; + rix[4]++; + } + + if(cc < cc1) { // remaining pixel, only if width is odd + rix[0][0] = rix[1][0] + rix[3][0]; + rix[2][0] = rix[1][0] + rix[4][0]; + } + } else { + c0 = 2 - c0; + int d = c0 + 3 - (c0 == 0 ? 0 : 1); + int cc; + + for (cc = 0; cc < cc1 - 1; cc += 2) { + rix[c0][0] = rix[1][0] + rix[d][0]; + rix[1][0] = 0.5f * (rix[0][0] - rix[3][0] + rix[2][0] - rix[4][0]); + rix[0]++; + rix[1]++; + rix[2]++; + rix[3]++; + rix[4]++; + rix[0][0] = rix[1][0] + rix[3][0]; + rix[2][0] = rix[1][0] + rix[4][0]; + rix[0]++; + rix[1]++; + rix[2]++; + rix[3]++; + rix[4]++; + } + + if(cc < cc1) { // remaining pixel, only if width is odd + rix[c0][0] = rix[1][0] + rix[d][0]; + rix[1][0] = 0.5f * (rix[0][0] - rix[3][0] + rix[2][0] - rix[4][0]); + } + } + } + } + + if (plistener) { + plistener->setProgress (0.8); + } + + if(applyGamma) { + gamtab = &(Color::igammatab_24_17); + } else { + gamtab->makeIdentity(); + } + + array2D* rgb[3]; + rgb[0] = &red; + rgb[1] = &green; + rgb[2] = &blue; + + // copy result back to image matrix +#ifdef _OPENMP + #pragma omp parallel for +#endif + + for (int row = 0; row < height; row++) { + for (int col = 0, rr = row + ba; col < width; col++) { + int cc = col + ba; + int c = FC(row, col); + + for (int ii = 0; ii < 3; ii++) + if (ii != c) { + float *rix = qix[ii] + rr * cc1 + cc; + (*(rgb[ii]))[row][col] = (*gamtab)[65535.f * rix[0]]; + } else { + (*(rgb[ii]))[row][col] = CLIP(rawData[row][col]); + } + } + } + + if (plistener) { + plistener->setProgress (1.0); + } + + if(buffer) { + free(buffer); + } else + for(int i = 0; i < 5; i++) { + free(qix[i]); + } + + if(!applyGamma) { + delete gamtab; + } + + if(iterations > 4 && iterations <= 6) { + refinement(passref); + } else if(iterations > 6) { + refinement_lassus(passref); + } + +} + +/*** +* +* Bayer CFA Demosaicing using Integrated Gaussian Vector on Color Differences +* Revision 1.0 - 2013/02/28 +* +* Copyright (c) 2007-2013 Luis Sanz Rodriguez +* Using High Order Interpolation technique by Jim S, Jimmy Li, and Sharmil Randhawa +* +* Contact info: luis.sanz.rodriguez@gmail.com +* +* This code is distributed under a GNU General Public License, version 3. +* Visit for more information. +* +***/ +// Adapted to RawTherapee by Jacques Desmis 3/2013 +// SSE version by Ingo Weyrich 5/2013 +#ifdef __SSE2__ +#define CLIPV(a) LIMV(a,zerov,c65535v) +void RawImageSource::igv_interpolate(int winw, int winh) +{ + static const float eps = 1e-5f, epssq = 1e-5f; //mod epssq -10f =>-5f Jacques 3/2013 to prevent artifact (divide by zero) + + static const int h1 = 1, h2 = 2, h3 = 3, h5 = 5; + const int width = winw, height = winh; + const int v1 = 1 * width, v2 = 2 * width, v3 = 3 * width, v5 = 5 * width; + float* rgb[2]; + float* chr[4]; + float *rgbarray, *vdif, *hdif, *chrarray; + rgbarray = (float (*)) malloc((width * height) * sizeof( float ) ); + rgb[0] = rgbarray; + rgb[1] = rgbarray + (width * height) / 2; + + vdif = (float (*)) calloc( width * height / 2, sizeof * vdif ); + hdif = (float (*)) calloc( width * height / 2, sizeof * hdif ); + + chrarray = (float (*)) calloc( width * height, sizeof( float ) ); + chr[0] = chrarray; + chr[1] = chrarray + (width * height) / 2; + + // mapped chr[2] and chr[3] to hdif and hdif, because these are out of use, when chr[2] and chr[3] are used + chr[2] = hdif; + chr[3] = vdif; + + border_interpolate2(winw, winh, 7); + + if (plistener) { + plistener->setProgressStr (Glib::ustring::compose(M("TP_RAW_DMETHOD_PROGRESSBAR"), RAWParams::BayerSensor::getMethodString(RAWParams::BayerSensor::Method::IGV))); + plistener->setProgress (0.0); + } + +#ifdef _OPENMP + #pragma omp parallel default(none) shared(rgb,vdif,hdif,chr) +#endif + { + __m128 ngv, egv, wgv, sgv, nvv, evv, wvv, svv, nwgv, negv, swgv, segv, nwvv, nevv, swvv, sevv, tempv, temp1v, temp2v, temp3v, temp4v, temp5v, temp6v, temp7v, temp8v; + __m128 epsv = _mm_set1_ps( eps ); + __m128 epssqv = _mm_set1_ps( epssq ); + __m128 c65535v = _mm_set1_ps( 65535.f ); + __m128 c23v = _mm_set1_ps( 23.f ); + __m128 c40v = _mm_set1_ps( 40.f ); + __m128 c51v = _mm_set1_ps( 51.f ); + __m128 c32v = _mm_set1_ps( 32.f ); + __m128 c8v = _mm_set1_ps( 8.f ); + __m128 c7v = _mm_set1_ps( 7.f ); + __m128 c6v = _mm_set1_ps( 6.f ); + __m128 c10v = _mm_set1_ps( 10.f ); + __m128 c21v = _mm_set1_ps( 21.f ); + __m128 c78v = _mm_set1_ps( 78.f ); + __m128 c69v = _mm_set1_ps( 69.f ); + __m128 c3145680v = _mm_set1_ps( 3145680.f ); + __m128 onev = _mm_set1_ps ( 1.f ); + __m128 zerov = _mm_set1_ps ( 0.f ); + __m128 d725v = _mm_set1_ps ( 0.725f ); + __m128 d1375v = _mm_set1_ps ( 0.1375f ); + + float *dest1, *dest2; + float ng, eg, wg, sg, nv, ev, wv, sv, nwg, neg, swg, seg, nwv, nev, swv, sev; +#ifdef _OPENMP + #pragma omp for +#endif + + for (int row = 0; row < height - 0; row++) { + dest1 = rgb[FC(row, 0) & 1]; + dest2 = rgb[FC(row, 1) & 1]; + int col, indx; + + for (col = 0, indx = row * width + col; col < width - 7; col += 8, indx += 8) { + temp1v = LVFU( rawData[row][col] ); + temp1v = CLIPV( temp1v ); + temp2v = LVFU( rawData[row][col + 4] ); + temp2v = CLIPV( temp2v ); + tempv = _mm_shuffle_ps( temp1v, temp2v, _MM_SHUFFLE( 2, 0, 2, 0 ) ); + _mm_storeu_ps( &dest1[indx >> 1], tempv ); + tempv = _mm_shuffle_ps( temp1v, temp2v, _MM_SHUFFLE( 3, 1, 3, 1 ) ); + _mm_storeu_ps( &dest2[indx >> 1], tempv ); + } + + for (; col < width; col++, indx += 2) { + dest1[indx >> 1] = CLIP(rawData[row][col]); //rawData = RT datas + col++; + if(col < width) + dest2[indx >> 1] = CLIP(rawData[row][col]); //rawData = RT datas + } + } + +#ifdef _OPENMP + #pragma omp single +#endif + { + if (plistener) { + plistener->setProgress (0.13); + } + } + +#ifdef _OPENMP + #pragma omp for +#endif + + for (int row = 5; row < height - 5; row++) { + int col, indx, indx1; + + for (col = 5 + (FC(row, 1) & 1), indx = row * width + col, indx1 = indx >> 1; col < width - 12; col += 8, indx += 8, indx1 += 4) { + //N,E,W,S Gradients + ngv = (epsv + (vabsf(LVFU(rgb[1][(indx - v1) >> 1]) - LVFU(rgb[1][(indx - v3) >> 1])) + vabsf(LVFU(rgb[0][indx1]) - LVFU(rgb[0][(indx1 - v1)]))) / c65535v); + egv = (epsv + (vabsf(LVFU(rgb[1][(indx + h1) >> 1]) - LVFU(rgb[1][(indx + h3) >> 1])) + vabsf(LVFU(rgb[0][indx1]) - LVFU(rgb[0][(indx1 + h1)]))) / c65535v); + wgv = (epsv + (vabsf(LVFU(rgb[1][(indx - h1) >> 1]) - LVFU(rgb[1][(indx - h3) >> 1])) + vabsf(LVFU(rgb[0][indx1]) - LVFU(rgb[0][(indx1 - h1)]))) / c65535v); + sgv = (epsv + (vabsf(LVFU(rgb[1][(indx + v1) >> 1]) - LVFU(rgb[1][(indx + v3) >> 1])) + vabsf(LVFU(rgb[0][indx1]) - LVFU(rgb[0][(indx1 + v1)]))) / c65535v); + //N,E,W,S High Order Interpolation (Li & Randhawa) + //N,E,W,S Hamilton Adams Interpolation + // (48.f * 65535.f) = 3145680.f + tempv = c40v * LVFU(rgb[0][indx1]); + nvv = LIMV(((c23v * LVFU(rgb[1][(indx - v1) >> 1]) + c23v * LVFU(rgb[1][(indx - v3) >> 1]) + LVFU(rgb[1][(indx - v5) >> 1]) + LVFU(rgb[1][(indx + v1) >> 1]) + tempv - c32v * LVFU(rgb[0][(indx1 - v1)]) - c8v * LVFU(rgb[0][(indx1 - v2)]))) / c3145680v, zerov, onev); + evv = LIMV(((c23v * LVFU(rgb[1][(indx + h1) >> 1]) + c23v * LVFU(rgb[1][(indx + h3) >> 1]) + LVFU(rgb[1][(indx + h5) >> 1]) + LVFU(rgb[1][(indx - h1) >> 1]) + tempv - c32v * LVFU(rgb[0][(indx1 + h1)]) - c8v * LVFU(rgb[0][(indx1 + h2)]))) / c3145680v, zerov, onev); + wvv = LIMV(((c23v * LVFU(rgb[1][(indx - h1) >> 1]) + c23v * LVFU(rgb[1][(indx - h3) >> 1]) + LVFU(rgb[1][(indx - h5) >> 1]) + LVFU(rgb[1][(indx + h1) >> 1]) + tempv - c32v * LVFU(rgb[0][(indx1 - h1)]) - c8v * LVFU(rgb[0][(indx1 - h2)]))) / c3145680v, zerov, onev); + svv = LIMV(((c23v * LVFU(rgb[1][(indx + v1) >> 1]) + c23v * LVFU(rgb[1][(indx + v3) >> 1]) + LVFU(rgb[1][(indx + v5) >> 1]) + LVFU(rgb[1][(indx - v1) >> 1]) + tempv - c32v * LVFU(rgb[0][(indx1 + v1)]) - c8v * LVFU(rgb[0][(indx1 + v2)]))) / c3145680v, zerov, onev); + //Horizontal and vertical color differences + tempv = LVFU( rgb[0][indx1] ) / c65535v; + _mm_storeu_ps( &vdif[indx1], (sgv * nvv + ngv * svv) / (ngv + sgv) - tempv ); + _mm_storeu_ps( &hdif[indx1], (wgv * evv + egv * wvv) / (egv + wgv) - tempv ); + } + + // borders without SSE + for (; col < width - 5; col += 2, indx += 2, indx1++) { + //N,E,W,S Gradients + ng = (eps + (fabsf(rgb[1][(indx - v1) >> 1] - rgb[1][(indx - v3) >> 1]) + fabsf(rgb[0][indx1] - rgb[0][(indx1 - v1)])) / 65535.f);; + eg = (eps + (fabsf(rgb[1][(indx + h1) >> 1] - rgb[1][(indx + h3) >> 1]) + fabsf(rgb[0][indx1] - rgb[0][(indx1 + h1)])) / 65535.f); + wg = (eps + (fabsf(rgb[1][(indx - h1) >> 1] - rgb[1][(indx - h3) >> 1]) + fabsf(rgb[0][indx1] - rgb[0][(indx1 - h1)])) / 65535.f); + sg = (eps + (fabsf(rgb[1][(indx + v1) >> 1] - rgb[1][(indx + v3) >> 1]) + fabsf(rgb[0][indx1] - rgb[0][(indx1 + v1)])) / 65535.f); + //N,E,W,S High Order Interpolation (Li & Randhawa) + //N,E,W,S Hamilton Adams Interpolation + // (48.f * 65535.f) = 3145680.f + nv = LIM(((23.0f * rgb[1][(indx - v1) >> 1] + 23.0f * rgb[1][(indx - v3) >> 1] + rgb[1][(indx - v5) >> 1] + rgb[1][(indx + v1) >> 1] + 40.0f * rgb[0][indx1] - 32.0f * rgb[0][(indx1 - v1)] - 8.0f * rgb[0][(indx1 - v2)])) / 3145680.f, 0.0f, 1.0f); + ev = LIM(((23.0f * rgb[1][(indx + h1) >> 1] + 23.0f * rgb[1][(indx + h3) >> 1] + rgb[1][(indx + h5) >> 1] + rgb[1][(indx - h1) >> 1] + 40.0f * rgb[0][indx1] - 32.0f * rgb[0][(indx1 + h1)] - 8.0f * rgb[0][(indx1 + h2)])) / 3145680.f, 0.0f, 1.0f); + wv = LIM(((23.0f * rgb[1][(indx - h1) >> 1] + 23.0f * rgb[1][(indx - h3) >> 1] + rgb[1][(indx - h5) >> 1] + rgb[1][(indx + h1) >> 1] + 40.0f * rgb[0][indx1] - 32.0f * rgb[0][(indx1 - h1)] - 8.0f * rgb[0][(indx1 - h2)])) / 3145680.f, 0.0f, 1.0f); + sv = LIM(((23.0f * rgb[1][(indx + v1) >> 1] + 23.0f * rgb[1][(indx + v3) >> 1] + rgb[1][(indx + v5) >> 1] + rgb[1][(indx - v1) >> 1] + 40.0f * rgb[0][indx1] - 32.0f * rgb[0][(indx1 + v1)] - 8.0f * rgb[0][(indx1 + v2)])) / 3145680.f, 0.0f, 1.0f); + //Horizontal and vertical color differences + vdif[indx1] = (sg * nv + ng * sv) / (ng + sg) - (rgb[0][indx1]) / 65535.f; + hdif[indx1] = (wg * ev + eg * wv) / (eg + wg) - (rgb[0][indx1]) / 65535.f; + } + } + +#ifdef _OPENMP + #pragma omp single +#endif + { + if (plistener) { + plistener->setProgress (0.26); + } + } +#ifdef _OPENMP + #pragma omp for +#endif + + for (int row = 7; row < height - 7; row++) { + int col, d, indx1; + + for (col = 7 + (FC(row, 1) & 1), indx1 = (row * width + col) >> 1, d = FC(row, col) / 2; col < width - 14; col += 8, indx1 += 4) { + //H&V integrated gaussian vector over variance on color differences + //Mod Jacques 3/2013 + ngv = LIMV(epssqv + c78v * SQRV(LVFU(vdif[indx1])) + c69v * (SQRV(LVFU(vdif[indx1 - v1])) + SQRV(LVFU(vdif[indx1 + v1]))) + c51v * (SQRV(LVFU(vdif[indx1 - v2])) + SQRV(LVFU(vdif[indx1 + v2]))) + c21v * (SQRV(LVFU(vdif[indx1 - v3])) + SQRV(LVFU(vdif[indx1 + v3]))) - c6v * SQRV(LVFU(vdif[indx1 - v1]) + LVFU(vdif[indx1]) + LVFU(vdif[indx1 + v1])) + - c10v * (SQRV(LVFU(vdif[indx1 - v2]) + LVFU(vdif[indx1 - v1]) + LVFU(vdif[indx1])) + SQRV(LVFU(vdif[indx1]) + LVFU(vdif[indx1 + v1]) + LVFU(vdif[indx1 + v2]))) - c7v * (SQRV(LVFU(vdif[indx1 - v3]) + LVFU(vdif[indx1 - v2]) + LVFU(vdif[indx1 - v1])) + SQRV(LVFU(vdif[indx1 + v1]) + LVFU(vdif[indx1 + v2]) + LVFU(vdif[indx1 + v3]))), zerov, onev); + egv = LIMV(epssqv + c78v * SQRV(LVFU(hdif[indx1])) + c69v * (SQRV(LVFU(hdif[indx1 - h1])) + SQRV(LVFU(hdif[indx1 + h1]))) + c51v * (SQRV(LVFU(hdif[indx1 - h2])) + SQRV(LVFU(hdif[indx1 + h2]))) + c21v * (SQRV(LVFU(hdif[indx1 - h3])) + SQRV(LVFU(hdif[indx1 + h3]))) - c6v * SQRV(LVFU(hdif[indx1 - h1]) + LVFU(hdif[indx1]) + LVFU(hdif[indx1 + h1])) + - c10v * (SQRV(LVFU(hdif[indx1 - h2]) + LVFU(hdif[indx1 - h1]) + LVFU(hdif[indx1])) + SQRV(LVFU(hdif[indx1]) + LVFU(hdif[indx1 + h1]) + LVFU(hdif[indx1 + h2]))) - c7v * (SQRV(LVFU(hdif[indx1 - h3]) + LVFU(hdif[indx1 - h2]) + LVFU(hdif[indx1 - h1])) + SQRV(LVFU(hdif[indx1 + h1]) + LVFU(hdif[indx1 + h2]) + LVFU(hdif[indx1 + h3]))), zerov, onev); + //Limit chrominance using H/V neighbourhood + nvv = median(d725v * LVFU(vdif[indx1]) + d1375v * LVFU(vdif[indx1 - v1]) + d1375v * LVFU(vdif[indx1 + v1]), LVFU(vdif[indx1 - v1]), LVFU(vdif[indx1 + v1])); + evv = median(d725v * LVFU(hdif[indx1]) + d1375v * LVFU(hdif[indx1 - h1]) + d1375v * LVFU(hdif[indx1 + h1]), LVFU(hdif[indx1 - h1]), LVFU(hdif[indx1 + h1])); + //Chrominance estimation + tempv = (egv * nvv + ngv * evv) / (ngv + egv); + _mm_storeu_ps(&(chr[d][indx1]), tempv); + //Green channel population + temp1v = c65535v * tempv + LVFU(rgb[0][indx1]); + _mm_storeu_ps( &(rgb[0][indx1]), temp1v ); + } + + for (; col < width - 7; col += 2, indx1++) { + //H&V integrated gaussian vector over variance on color differences + //Mod Jacques 3/2013 + ng = LIM(epssq + 78.0f * SQR(vdif[indx1]) + 69.0f * (SQR(vdif[indx1 - v1]) + SQR(vdif[indx1 + v1])) + 51.0f * (SQR(vdif[indx1 - v2]) + SQR(vdif[indx1 + v2])) + 21.0f * (SQR(vdif[indx1 - v3]) + SQR(vdif[indx1 + v3])) - 6.0f * SQR(vdif[indx1 - v1] + vdif[indx1] + vdif[indx1 + v1]) + - 10.0f * (SQR(vdif[indx1 - v2] + vdif[indx1 - v1] + vdif[indx1]) + SQR(vdif[indx1] + vdif[indx1 + v1] + vdif[indx1 + v2])) - 7.0f * (SQR(vdif[indx1 - v3] + vdif[indx1 - v2] + vdif[indx1 - v1]) + SQR(vdif[indx1 + v1] + vdif[indx1 + v2] + vdif[indx1 + v3])), 0.f, 1.f); + eg = LIM(epssq + 78.0f * SQR(hdif[indx1]) + 69.0f * (SQR(hdif[indx1 - h1]) + SQR(hdif[indx1 + h1])) + 51.0f * (SQR(hdif[indx1 - h2]) + SQR(hdif[indx1 + h2])) + 21.0f * (SQR(hdif[indx1 - h3]) + SQR(hdif[indx1 + h3])) - 6.0f * SQR(hdif[indx1 - h1] + hdif[indx1] + hdif[indx1 + h1]) + - 10.0f * (SQR(hdif[indx1 - h2] + hdif[indx1 - h1] + hdif[indx1]) + SQR(hdif[indx1] + hdif[indx1 + h1] + hdif[indx1 + h2])) - 7.0f * (SQR(hdif[indx1 - h3] + hdif[indx1 - h2] + hdif[indx1 - h1]) + SQR(hdif[indx1 + h1] + hdif[indx1 + h2] + hdif[indx1 + h3])), 0.f, 1.f); + //Limit chrominance using H/V neighbourhood + nv = median(0.725f * vdif[indx1] + 0.1375f * vdif[indx1 - v1] + 0.1375f * vdif[indx1 + v1], vdif[indx1 - v1], vdif[indx1 + v1]); + ev = median(0.725f * hdif[indx1] + 0.1375f * hdif[indx1 - h1] + 0.1375f * hdif[indx1 + h1], hdif[indx1 - h1], hdif[indx1 + h1]); + //Chrominance estimation + chr[d][indx1] = (eg * nv + ng * ev) / (ng + eg); + //Green channel population + rgb[0][indx1] = rgb[0][indx1] + 65535.f * chr[d][indx1]; + } + } + +#ifdef _OPENMP + #pragma omp single +#endif + { + if (plistener) { + plistener->setProgress (0.39); + } + } +#ifdef _OPENMP + #pragma omp for +#endif + + for (int row = 7; row < height - 7; row++) { + int col, indx, c; + + for (col = 7 + (FC(row, 1) & 1), indx = row * width + col, c = 1 - FC(row, col) / 2; col < width - 14; col += 8, indx += 8) { + //NW,NE,SW,SE Gradients + nwgv = onev / (epsv + vabsf(LVFU(chr[c][(indx - v1 - h1) >> 1]) - LVFU(chr[c][(indx - v3 - h3) >> 1])) + vabsf(LVFU(chr[c][(indx + v1 + h1) >> 1]) - LVFU(chr[c][(indx - v3 - h3) >> 1]))); + negv = onev / (epsv + vabsf(LVFU(chr[c][(indx - v1 + h1) >> 1]) - LVFU(chr[c][(indx - v3 + h3) >> 1])) + vabsf(LVFU(chr[c][(indx + v1 - h1) >> 1]) - LVFU(chr[c][(indx - v3 + h3) >> 1]))); + swgv = onev / (epsv + vabsf(LVFU(chr[c][(indx + v1 - h1) >> 1]) - LVFU(chr[c][(indx + v3 + h3) >> 1])) + vabsf(LVFU(chr[c][(indx - v1 + h1) >> 1]) - LVFU(chr[c][(indx + v3 - h3) >> 1]))); + segv = onev / (epsv + vabsf(LVFU(chr[c][(indx + v1 + h1) >> 1]) - LVFU(chr[c][(indx + v3 - h3) >> 1])) + vabsf(LVFU(chr[c][(indx - v1 - h1) >> 1]) - LVFU(chr[c][(indx + v3 + h3) >> 1]))); + //Limit NW,NE,SW,SE Color differences + nwvv = median(LVFU(chr[c][(indx - v1 - h1) >> 1]), LVFU(chr[c][(indx - v3 - h1) >> 1]), LVFU(chr[c][(indx - v1 - h3) >> 1])); + nevv = median(LVFU(chr[c][(indx - v1 + h1) >> 1]), LVFU(chr[c][(indx - v3 + h1) >> 1]), LVFU(chr[c][(indx - v1 + h3) >> 1])); + swvv = median(LVFU(chr[c][(indx + v1 - h1) >> 1]), LVFU(chr[c][(indx + v3 - h1) >> 1]), LVFU(chr[c][(indx + v1 - h3) >> 1])); + sevv = median(LVFU(chr[c][(indx + v1 + h1) >> 1]), LVFU(chr[c][(indx + v3 + h1) >> 1]), LVFU(chr[c][(indx + v1 + h3) >> 1])); + //Interpolate chrominance: R@B and B@R + tempv = (nwgv * nwvv + negv * nevv + swgv * swvv + segv * sevv) / (nwgv + negv + swgv + segv); + _mm_storeu_ps( &(chr[c][indx >> 1]), tempv); + } + + for (; col < width - 7; col += 2, indx += 2) { + //NW,NE,SW,SE Gradients + nwg = 1.0f / (eps + fabsf(chr[c][(indx - v1 - h1) >> 1] - chr[c][(indx - v3 - h3) >> 1]) + fabsf(chr[c][(indx + v1 + h1) >> 1] - chr[c][(indx - v3 - h3) >> 1])); + neg = 1.0f / (eps + fabsf(chr[c][(indx - v1 + h1) >> 1] - chr[c][(indx - v3 + h3) >> 1]) + fabsf(chr[c][(indx + v1 - h1) >> 1] - chr[c][(indx - v3 + h3) >> 1])); + swg = 1.0f / (eps + fabsf(chr[c][(indx + v1 - h1) >> 1] - chr[c][(indx + v3 + h3) >> 1]) + fabsf(chr[c][(indx - v1 + h1) >> 1] - chr[c][(indx + v3 - h3) >> 1])); + seg = 1.0f / (eps + fabsf(chr[c][(indx + v1 + h1) >> 1] - chr[c][(indx + v3 - h3) >> 1]) + fabsf(chr[c][(indx - v1 - h1) >> 1] - chr[c][(indx + v3 + h3) >> 1])); + //Limit NW,NE,SW,SE Color differences + nwv = median(chr[c][(indx - v1 - h1) >> 1], chr[c][(indx - v3 - h1) >> 1], chr[c][(indx - v1 - h3) >> 1]); + nev = median(chr[c][(indx - v1 + h1) >> 1], chr[c][(indx - v3 + h1) >> 1], chr[c][(indx - v1 + h3) >> 1]); + swv = median(chr[c][(indx + v1 - h1) >> 1], chr[c][(indx + v3 - h1) >> 1], chr[c][(indx + v1 - h3) >> 1]); + sev = median(chr[c][(indx + v1 + h1) >> 1], chr[c][(indx + v3 + h1) >> 1], chr[c][(indx + v1 + h3) >> 1]); + //Interpolate chrominance: R@B and B@R + chr[c][indx >> 1] = (nwg * nwv + neg * nev + swg * swv + seg * sev) / (nwg + neg + swg + seg); + } + } + +#ifdef _OPENMP + #pragma omp single +#endif + { + if (plistener) { + plistener->setProgress (0.65); + } + } +#ifdef _OPENMP + #pragma omp for +#endif + + for (int row = 7; row < height - 7; row++) { + int col, indx; + + for (col = 7 + (FC(row, 0) & 1), indx = row * width + col; col < width - 14; col += 8, indx += 8) { + //N,E,W,S Gradients + ngv = onev / (epsv + vabsf(LVFU(chr[0][(indx - v1) >> 1]) - LVFU(chr[0][(indx - v3) >> 1])) + vabsf(LVFU(chr[0][(indx + v1) >> 1]) - LVFU(chr[0][(indx - v3) >> 1]))); + egv = onev / (epsv + vabsf(LVFU(chr[0][(indx + h1) >> 1]) - LVFU(chr[0][(indx + h3) >> 1])) + vabsf(LVFU(chr[0][(indx - h1) >> 1]) - LVFU(chr[0][(indx + h3) >> 1]))); + wgv = onev / (epsv + vabsf(LVFU(chr[0][(indx - h1) >> 1]) - LVFU(chr[0][(indx - h3) >> 1])) + vabsf(LVFU(chr[0][(indx + h1) >> 1]) - LVFU(chr[0][(indx - h3) >> 1]))); + sgv = onev / (epsv + vabsf(LVFU(chr[0][(indx + v1) >> 1]) - LVFU(chr[0][(indx + v3) >> 1])) + vabsf(LVFU(chr[0][(indx - v1) >> 1]) - LVFU(chr[0][(indx + v3) >> 1]))); + //Interpolate chrominance: R@G and B@G + tempv = ((ngv * LVFU(chr[0][(indx - v1) >> 1]) + egv * LVFU(chr[0][(indx + h1) >> 1]) + wgv * LVFU(chr[0][(indx - h1) >> 1]) + sgv * LVFU(chr[0][(indx + v1) >> 1])) / (ngv + egv + wgv + sgv)); + _mm_storeu_ps( &chr[0 + 2][indx >> 1], tempv); + } + + for (; col < width - 7; col += 2, indx += 2) { + //N,E,W,S Gradients + ng = 1.0f / (eps + fabsf(chr[0][(indx - v1) >> 1] - chr[0][(indx - v3) >> 1]) + fabsf(chr[0][(indx + v1) >> 1] - chr[0][(indx - v3) >> 1])); + eg = 1.0f / (eps + fabsf(chr[0][(indx + h1) >> 1] - chr[0][(indx + h3) >> 1]) + fabsf(chr[0][(indx - h1) >> 1] - chr[0][(indx + h3) >> 1])); + wg = 1.0f / (eps + fabsf(chr[0][(indx - h1) >> 1] - chr[0][(indx - h3) >> 1]) + fabsf(chr[0][(indx + h1) >> 1] - chr[0][(indx - h3) >> 1])); + sg = 1.0f / (eps + fabsf(chr[0][(indx + v1) >> 1] - chr[0][(indx + v3) >> 1]) + fabsf(chr[0][(indx - v1) >> 1] - chr[0][(indx + v3) >> 1])); + //Interpolate chrominance: R@G and B@G + chr[0 + 2][indx >> 1] = ((ng * chr[0][(indx - v1) >> 1] + eg * chr[0][(indx + h1) >> 1] + wg * chr[0][(indx - h1) >> 1] + sg * chr[0][(indx + v1) >> 1]) / (ng + eg + wg + sg)); + } + } + +#ifdef _OPENMP + #pragma omp single +#endif + { + if (plistener) { + plistener->setProgress (0.78); + } + } +#ifdef _OPENMP + #pragma omp for +#endif + + for (int row = 7; row < height - 7; row++) { + int col, indx; + + for (col = 7 + (FC(row, 0) & 1), indx = row * width + col; col < width - 14; col += 8, indx += 8) { + //N,E,W,S Gradients + ngv = onev / (epsv + vabsf(LVFU(chr[1][(indx - v1) >> 1]) - LVFU(chr[1][(indx - v3) >> 1])) + vabsf(LVFU(chr[1][(indx + v1) >> 1]) - LVFU(chr[1][(indx - v3) >> 1]))); + egv = onev / (epsv + vabsf(LVFU(chr[1][(indx + h1) >> 1]) - LVFU(chr[1][(indx + h3) >> 1])) + vabsf(LVFU(chr[1][(indx - h1) >> 1]) - LVFU(chr[1][(indx + h3) >> 1]))); + wgv = onev / (epsv + vabsf(LVFU(chr[1][(indx - h1) >> 1]) - LVFU(chr[1][(indx - h3) >> 1])) + vabsf(LVFU(chr[1][(indx + h1) >> 1]) - LVFU(chr[1][(indx - h3) >> 1]))); + sgv = onev / (epsv + vabsf(LVFU(chr[1][(indx + v1) >> 1]) - LVFU(chr[1][(indx + v3) >> 1])) + vabsf(LVFU(chr[1][(indx - v1) >> 1]) - LVFU(chr[1][(indx + v3) >> 1]))); + //Interpolate chrominance: R@G and B@G + tempv = ((ngv * LVFU(chr[1][(indx - v1) >> 1]) + egv * LVFU(chr[1][(indx + h1) >> 1]) + wgv * LVFU(chr[1][(indx - h1) >> 1]) + sgv * LVFU(chr[1][(indx + v1) >> 1])) / (ngv + egv + wgv + sgv)); + _mm_storeu_ps( &chr[1 + 2][indx >> 1], tempv); + } + + for (; col < width - 7; col += 2, indx += 2) { + //N,E,W,S Gradients + ng = 1.0f / (eps + fabsf(chr[1][(indx - v1) >> 1] - chr[1][(indx - v3) >> 1]) + fabsf(chr[1][(indx + v1) >> 1] - chr[1][(indx - v3) >> 1])); + eg = 1.0f / (eps + fabsf(chr[1][(indx + h1) >> 1] - chr[1][(indx + h3) >> 1]) + fabsf(chr[1][(indx - h1) >> 1] - chr[1][(indx + h3) >> 1])); + wg = 1.0f / (eps + fabsf(chr[1][(indx - h1) >> 1] - chr[1][(indx - h3) >> 1]) + fabsf(chr[1][(indx + h1) >> 1] - chr[1][(indx - h3) >> 1])); + sg = 1.0f / (eps + fabsf(chr[1][(indx + v1) >> 1] - chr[1][(indx + v3) >> 1]) + fabsf(chr[1][(indx - v1) >> 1] - chr[1][(indx + v3) >> 1])); + //Interpolate chrominance: R@G and B@G + chr[1 + 2][indx >> 1] = ((ng * chr[1][(indx - v1) >> 1] + eg * chr[1][(indx + h1) >> 1] + wg * chr[1][(indx - h1) >> 1] + sg * chr[1][(indx + v1) >> 1]) / (ng + eg + wg + sg)); + } + } + +#ifdef _OPENMP + #pragma omp single +#endif + { + if (plistener) { + plistener->setProgress (0.91); + } + } + float *src1, *src2, *redsrc0, *redsrc1, *bluesrc0, *bluesrc1; +#ifdef _OPENMP + #pragma omp for +#endif + + for(int row = 7; row < height - 7; row++) { + int col, indx, fc; + fc = FC(row, 7) & 1; + src1 = rgb[fc]; + src2 = rgb[fc ^ 1]; + redsrc0 = chr[fc << 1]; + redsrc1 = chr[(fc ^ 1) << 1]; + bluesrc0 = chr[(fc << 1) + 1]; + bluesrc1 = chr[((fc ^ 1) << 1) + 1]; + + for(col = 7, indx = row * width + col; col < width - 14; col += 8, indx += 8) { + temp1v = LVFU( src1[indx >> 1] ); + temp2v = LVFU( src2[(indx + 1) >> 1] ); + tempv = _mm_shuffle_ps( temp1v, temp2v, _MM_SHUFFLE( 1, 0, 1, 0 ) ); + tempv = _mm_shuffle_ps( tempv, tempv, _MM_SHUFFLE( 3, 1, 2, 0 ) ); + _mm_storeu_ps( &green[row][col], CLIPV( tempv )); + temp5v = LVFU(redsrc0[indx >> 1]); + temp6v = LVFU(redsrc1[(indx + 1) >> 1]); + temp3v = _mm_shuffle_ps( temp5v, temp6v, _MM_SHUFFLE( 1, 0, 1, 0 ) ); + temp3v = _mm_shuffle_ps( temp3v, temp3v, _MM_SHUFFLE( 3, 1, 2, 0 ) ); + temp3v = CLIPV( tempv - c65535v * temp3v ); + _mm_storeu_ps( &red[row][col], temp3v); + temp7v = LVFU(bluesrc0[indx >> 1]); + temp8v = LVFU(bluesrc1[(indx + 1) >> 1]); + temp4v = _mm_shuffle_ps( temp7v, temp8v, _MM_SHUFFLE( 1, 0, 1, 0 ) ); + temp4v = _mm_shuffle_ps( temp4v, temp4v, _MM_SHUFFLE( 3, 1, 2, 0 ) ); + temp4v = CLIPV( tempv - c65535v * temp4v ); + _mm_storeu_ps( &blue[row][col], temp4v); + + tempv = _mm_shuffle_ps( temp1v, temp2v, _MM_SHUFFLE( 3, 2, 3, 2 ) ); + tempv = _mm_shuffle_ps( tempv, tempv, _MM_SHUFFLE( 3, 1, 2, 0 ) ); + _mm_storeu_ps( &green[row][col + 4], CLIPV( tempv )); + + temp3v = _mm_shuffle_ps( temp5v, temp6v, _MM_SHUFFLE( 3, 2, 3, 2 ) ); + temp3v = _mm_shuffle_ps( temp3v, temp3v, _MM_SHUFFLE( 3, 1, 2, 0 ) ); + temp3v = CLIPV( tempv - c65535v * temp3v ); + _mm_storeu_ps( &red[row][col + 4], temp3v); + temp4v = _mm_shuffle_ps( temp7v, temp8v, _MM_SHUFFLE( 3, 2, 3, 2 ) ); + temp4v = _mm_shuffle_ps( temp4v, temp4v, _MM_SHUFFLE( 3, 1, 2, 0 ) ); + temp4v = CLIPV( tempv - c65535v * temp4v ); + _mm_storeu_ps( &blue[row][col + 4], temp4v); + } + + for(; col < width - 7; col++, indx += 2) { + red [row][col] = CLIP(src1[indx >> 1] - 65535.f * redsrc0[indx >> 1]); + green[row][col] = CLIP(src1[indx >> 1]); + blue [row][col] = CLIP(src1[indx >> 1] - 65535.f * bluesrc0[indx >> 1]); + col++; + red [row][col] = CLIP(src2[(indx + 1) >> 1] - 65535.f * redsrc1[(indx + 1) >> 1]); + green[row][col] = CLIP(src2[(indx + 1) >> 1]); + blue [row][col] = CLIP(src2[(indx + 1) >> 1] - 65535.f * bluesrc1[(indx + 1) >> 1]); + } + } + }// End of parallelization + + if (plistener) { + plistener->setProgress (1.0); + } + + free(chrarray); + free(rgbarray); + free(vdif); + free(hdif); +} +#undef CLIPV +#else +void RawImageSource::igv_interpolate(int winw, int winh) +{ + static const float eps = 1e-5f, epssq = 1e-5f; //mod epssq -10f =>-5f Jacques 3/2013 to prevent artifact (divide by zero) + static const int h1 = 1, h2 = 2, h3 = 3, h4 = 4, h5 = 5, h6 = 6; + const int width = winw, height = winh; + const int v1 = 1 * width, v2 = 2 * width, v3 = 3 * width, v4 = 4 * width, v5 = 5 * width, v6 = 6 * width; + float* rgb[3]; + float* chr[2]; + float (*rgbarray), *vdif, *hdif, (*chrarray); + + rgbarray = (float (*)) calloc(width * height * 3, sizeof( float)); + rgb[0] = rgbarray; + rgb[1] = rgbarray + (width * height); + rgb[2] = rgbarray + 2 * (width * height); + + chrarray = (float (*)) calloc(width * height * 2, sizeof( float)); + chr[0] = chrarray; + chr[1] = chrarray + (width * height); + + vdif = (float (*)) calloc(width * height / 2, sizeof * vdif); + hdif = (float (*)) calloc(width * height / 2, sizeof * hdif); + + border_interpolate2(winw, winh, 7); + + if (plistener) { + plistener->setProgressStr (Glib::ustring::compose(M("TP_RAW_DMETHOD_PROGRESSBAR"), RAWParams::BayerSensor::getMethodString(RAWParams::BayerSensor::Method::IGV))); + plistener->setProgress (0.0); + } + +#ifdef _OPENMP + #pragma omp parallel default(none) shared(rgb,vdif,hdif,chr) +#endif + { + + float ng, eg, wg, sg, nv, ev, wv, sv, nwg, neg, swg, seg, nwv, nev, swv, sev; + +#ifdef _OPENMP + #pragma omp for +#endif + + for (int row = 0; row < height - 0; row++) + for (int col = 0, indx = row * width + col; col < width - 0; col++, indx++) { + int c = FC(row, col); + rgb[c][indx] = CLIP(rawData[row][col]); //rawData = RT datas + } + +// border_interpolate2(7, rgb); + +#ifdef _OPENMP + #pragma omp single +#endif + { + if (plistener) { + plistener->setProgress (0.13); + } + } + +#ifdef _OPENMP + #pragma omp for +#endif + + for (int row = 5; row < height - 5; row++) + for (int col = 5 + (FC(row, 1) & 1), indx = row * width + col, c = FC(row, col); col < width - 5; col += 2, indx += 2) { + //N,E,W,S Gradients + ng = (eps + (fabsf(rgb[1][indx - v1] - rgb[1][indx - v3]) + fabsf(rgb[c][indx] - rgb[c][indx - v2])) / 65535.f);; + eg = (eps + (fabsf(rgb[1][indx + h1] - rgb[1][indx + h3]) + fabsf(rgb[c][indx] - rgb[c][indx + h2])) / 65535.f); + wg = (eps + (fabsf(rgb[1][indx - h1] - rgb[1][indx - h3]) + fabsf(rgb[c][indx] - rgb[c][indx - h2])) / 65535.f); + sg = (eps + (fabsf(rgb[1][indx + v1] - rgb[1][indx + v3]) + fabsf(rgb[c][indx] - rgb[c][indx + v2])) / 65535.f); + //N,E,W,S High Order Interpolation (Li & Randhawa) + //N,E,W,S Hamilton Adams Interpolation + // (48.f * 65535.f) = 3145680.f + nv = LIM(((23.0f * rgb[1][indx - v1] + 23.0f * rgb[1][indx - v3] + rgb[1][indx - v5] + rgb[1][indx + v1] + 40.0f * rgb[c][indx] - 32.0f * rgb[c][indx - v2] - 8.0f * rgb[c][indx - v4])) / 3145680.f, 0.0f, 1.0f); + ev = LIM(((23.0f * rgb[1][indx + h1] + 23.0f * rgb[1][indx + h3] + rgb[1][indx + h5] + rgb[1][indx - h1] + 40.0f * rgb[c][indx] - 32.0f * rgb[c][indx + h2] - 8.0f * rgb[c][indx + h4])) / 3145680.f, 0.0f, 1.0f); + wv = LIM(((23.0f * rgb[1][indx - h1] + 23.0f * rgb[1][indx - h3] + rgb[1][indx - h5] + rgb[1][indx + h1] + 40.0f * rgb[c][indx] - 32.0f * rgb[c][indx - h2] - 8.0f * rgb[c][indx - h4])) / 3145680.f, 0.0f, 1.0f); + sv = LIM(((23.0f * rgb[1][indx + v1] + 23.0f * rgb[1][indx + v3] + rgb[1][indx + v5] + rgb[1][indx - v1] + 40.0f * rgb[c][indx] - 32.0f * rgb[c][indx + v2] - 8.0f * rgb[c][indx + v4])) / 3145680.f, 0.0f, 1.0f); + //Horizontal and vertical color differences + vdif[indx >> 1] = (sg * nv + ng * sv) / (ng + sg) - (rgb[c][indx]) / 65535.f; + hdif[indx >> 1] = (wg * ev + eg * wv) / (eg + wg) - (rgb[c][indx]) / 65535.f; + } + +#ifdef _OPENMP + #pragma omp single +#endif + { + if (plistener) { + plistener->setProgress (0.26); + } + } + +#ifdef _OPENMP + #pragma omp for +#endif + + for (int row = 7; row < height - 7; row++) + for (int col = 7 + (FC(row, 1) & 1), indx = row * width + col, c = FC(row, col), d = c / 2; col < width - 7; col += 2, indx += 2) { + //H&V integrated gaussian vector over variance on color differences + //Mod Jacques 3/2013 + ng = LIM(epssq + 78.0f * SQR(vdif[indx >> 1]) + 69.0f * (SQR(vdif[(indx - v2) >> 1]) + SQR(vdif[(indx + v2) >> 1])) + 51.0f * (SQR(vdif[(indx - v4) >> 1]) + SQR(vdif[(indx + v4) >> 1])) + 21.0f * (SQR(vdif[(indx - v6) >> 1]) + SQR(vdif[(indx + v6) >> 1])) - 6.0f * SQR(vdif[(indx - v2) >> 1] + vdif[indx >> 1] + vdif[(indx + v2) >> 1]) + - 10.0f * (SQR(vdif[(indx - v4) >> 1] + vdif[(indx - v2) >> 1] + vdif[indx >> 1]) + SQR(vdif[indx >> 1] + vdif[(indx + v2) >> 1] + vdif[(indx + v4) >> 1])) - 7.0f * (SQR(vdif[(indx - v6) >> 1] + vdif[(indx - v4) >> 1] + vdif[(indx - v2) >> 1]) + SQR(vdif[(indx + v2) >> 1] + vdif[(indx + v4) >> 1] + vdif[(indx + v6) >> 1])), 0.f, 1.f); + eg = LIM(epssq + 78.0f * SQR(hdif[indx >> 1]) + 69.0f * (SQR(hdif[(indx - h2) >> 1]) + SQR(hdif[(indx + h2) >> 1])) + 51.0f * (SQR(hdif[(indx - h4) >> 1]) + SQR(hdif[(indx + h4) >> 1])) + 21.0f * (SQR(hdif[(indx - h6) >> 1]) + SQR(hdif[(indx + h6) >> 1])) - 6.0f * SQR(hdif[(indx - h2) >> 1] + hdif[indx >> 1] + hdif[(indx + h2) >> 1]) + - 10.0f * (SQR(hdif[(indx - h4) >> 1] + hdif[(indx - h2) >> 1] + hdif[indx >> 1]) + SQR(hdif[indx >> 1] + hdif[(indx + h2) >> 1] + hdif[(indx + h4) >> 1])) - 7.0f * (SQR(hdif[(indx - h6) >> 1] + hdif[(indx - h4) >> 1] + hdif[(indx - h2) >> 1]) + SQR(hdif[(indx + h2) >> 1] + hdif[(indx + h4) >> 1] + hdif[(indx + h6) >> 1])), 0.f, 1.f); + //Limit chrominance using H/V neighbourhood + nv = median(0.725f * vdif[indx >> 1] + 0.1375f * vdif[(indx - v2) >> 1] + 0.1375f * vdif[(indx + v2) >> 1], vdif[(indx - v2) >> 1], vdif[(indx + v2) >> 1]); + ev = median(0.725f * hdif[indx >> 1] + 0.1375f * hdif[(indx - h2) >> 1] + 0.1375f * hdif[(indx + h2) >> 1], hdif[(indx - h2) >> 1], hdif[(indx + h2) >> 1]); + //Chrominance estimation + chr[d][indx] = (eg * nv + ng * ev) / (ng + eg); + //Green channel population + rgb[1][indx] = rgb[c][indx] + 65535.f * chr[d][indx]; + } + +#ifdef _OPENMP + #pragma omp single +#endif + { + if (plistener) { + plistener->setProgress (0.39); + } + } + +// free(vdif); free(hdif); +#ifdef _OPENMP + #pragma omp for +#endif + + for (int row = 7; row < height - 7; row += 2) + for (int col = 7 + (FC(row, 1) & 1), indx = row * width + col, c = 1 - FC(row, col) / 2; col < width - 7; col += 2, indx += 2) { + //NW,NE,SW,SE Gradients + nwg = 1.0f / (eps + fabsf(chr[c][indx - v1 - h1] - chr[c][indx - v3 - h3]) + fabsf(chr[c][indx + v1 + h1] - chr[c][indx - v3 - h3])); + neg = 1.0f / (eps + fabsf(chr[c][indx - v1 + h1] - chr[c][indx - v3 + h3]) + fabsf(chr[c][indx + v1 - h1] - chr[c][indx - v3 + h3])); + swg = 1.0f / (eps + fabsf(chr[c][indx + v1 - h1] - chr[c][indx + v3 + h3]) + fabsf(chr[c][indx - v1 + h1] - chr[c][indx + v3 - h3])); + seg = 1.0f / (eps + fabsf(chr[c][indx + v1 + h1] - chr[c][indx + v3 - h3]) + fabsf(chr[c][indx - v1 - h1] - chr[c][indx + v3 + h3])); + //Limit NW,NE,SW,SE Color differences + nwv = median(chr[c][indx - v1 - h1], chr[c][indx - v3 - h1], chr[c][indx - v1 - h3]); + nev = median(chr[c][indx - v1 + h1], chr[c][indx - v3 + h1], chr[c][indx - v1 + h3]); + swv = median(chr[c][indx + v1 - h1], chr[c][indx + v3 - h1], chr[c][indx + v1 - h3]); + sev = median(chr[c][indx + v1 + h1], chr[c][indx + v3 + h1], chr[c][indx + v1 + h3]); + //Interpolate chrominance: R@B and B@R + chr[c][indx] = (nwg * nwv + neg * nev + swg * swv + seg * sev) / (nwg + neg + swg + seg); + } + +#ifdef _OPENMP + #pragma omp single +#endif + { + if (plistener) { + plistener->setProgress (0.52); + } + } +#ifdef _OPENMP + #pragma omp for +#endif + + for (int row = 8; row < height - 7; row += 2) + for (int col = 7 + (FC(row, 1) & 1), indx = row * width + col, c = 1 - FC(row, col) / 2; col < width - 7; col += 2, indx += 2) { + //NW,NE,SW,SE Gradients + nwg = 1.0f / (eps + fabsf(chr[c][indx - v1 - h1] - chr[c][indx - v3 - h3]) + fabsf(chr[c][indx + v1 + h1] - chr[c][indx - v3 - h3])); + neg = 1.0f / (eps + fabsf(chr[c][indx - v1 + h1] - chr[c][indx - v3 + h3]) + fabsf(chr[c][indx + v1 - h1] - chr[c][indx - v3 + h3])); + swg = 1.0f / (eps + fabsf(chr[c][indx + v1 - h1] - chr[c][indx + v3 + h3]) + fabsf(chr[c][indx - v1 + h1] - chr[c][indx + v3 - h3])); + seg = 1.0f / (eps + fabsf(chr[c][indx + v1 + h1] - chr[c][indx + v3 - h3]) + fabsf(chr[c][indx - v1 - h1] - chr[c][indx + v3 + h3])); + //Limit NW,NE,SW,SE Color differences + nwv = median(chr[c][indx - v1 - h1], chr[c][indx - v3 - h1], chr[c][indx - v1 - h3]); + nev = median(chr[c][indx - v1 + h1], chr[c][indx - v3 + h1], chr[c][indx - v1 + h3]); + swv = median(chr[c][indx + v1 - h1], chr[c][indx + v3 - h1], chr[c][indx + v1 - h3]); + sev = median(chr[c][indx + v1 + h1], chr[c][indx + v3 + h1], chr[c][indx + v1 + h3]); + //Interpolate chrominance: R@B and B@R + chr[c][indx] = (nwg * nwv + neg * nev + swg * swv + seg * sev) / (nwg + neg + swg + seg); + } + +#ifdef _OPENMP + #pragma omp single +#endif + { + if (plistener) { + plistener->setProgress (0.65); + } + } +#ifdef _OPENMP + #pragma omp for +#endif + + for (int row = 7; row < height - 7; row++) + for (int col = 7 + (FC(row, 0) & 1), indx = row * width + col; col < width - 7; col += 2, indx += 2) { + //N,E,W,S Gradients + ng = 1.0f / (eps + fabsf(chr[0][indx - v1] - chr[0][indx - v3]) + fabsf(chr[0][indx + v1] - chr[0][indx - v3])); + eg = 1.0f / (eps + fabsf(chr[0][indx + h1] - chr[0][indx + h3]) + fabsf(chr[0][indx - h1] - chr[0][indx + h3])); + wg = 1.0f / (eps + fabsf(chr[0][indx - h1] - chr[0][indx - h3]) + fabsf(chr[0][indx + h1] - chr[0][indx - h3])); + sg = 1.0f / (eps + fabsf(chr[0][indx + v1] - chr[0][indx + v3]) + fabsf(chr[0][indx - v1] - chr[0][indx + v3])); + //Interpolate chrominance: R@G and B@G + chr[0][indx] = ((ng * chr[0][indx - v1] + eg * chr[0][indx + h1] + wg * chr[0][indx - h1] + sg * chr[0][indx + v1]) / (ng + eg + wg + sg)); + } + +#ifdef _OPENMP + #pragma omp single +#endif + { + if (plistener) { + plistener->setProgress (0.78); + } + } +#ifdef _OPENMP + #pragma omp for +#endif + + for (int row = 7; row < height - 7; row++) + for (int col = 7 + (FC(row, 0) & 1), indx = row * width + col; col < width - 7; col += 2, indx += 2) { + + //N,E,W,S Gradients + ng = 1.0f / (eps + fabsf(chr[1][indx - v1] - chr[1][indx - v3]) + fabsf(chr[1][indx + v1] - chr[1][indx - v3])); + eg = 1.0f / (eps + fabsf(chr[1][indx + h1] - chr[1][indx + h3]) + fabsf(chr[1][indx - h1] - chr[1][indx + h3])); + wg = 1.0f / (eps + fabsf(chr[1][indx - h1] - chr[1][indx - h3]) + fabsf(chr[1][indx + h1] - chr[1][indx - h3])); + sg = 1.0f / (eps + fabsf(chr[1][indx + v1] - chr[1][indx + v3]) + fabsf(chr[1][indx - v1] - chr[1][indx + v3])); + //Interpolate chrominance: R@G and B@G + chr[1][indx] = ((ng * chr[1][indx - v1] + eg * chr[1][indx + h1] + wg * chr[1][indx - h1] + sg * chr[1][indx + v1]) / (ng + eg + wg + sg)); + } + +#ifdef _OPENMP + #pragma omp single +#endif + { + if (plistener) { + plistener->setProgress (0.91); + } + + //Interpolate borders +// border_interpolate2(7, rgb); + } + /* +#ifdef _OPENMP + #pragma omp for +#endif + for (int row=0; row < height; row++) //borders + for (int col=0; col < width; col++) { + if (col==7 && row >= 7 && row < height-7) + col = width-7; + int indxc=row*width+col; + red [row][col] = rgb[indxc][0]; + green[row][col] = rgb[indxc][1]; + blue [row][col] = rgb[indxc][2]; + } + */ + +#ifdef _OPENMP + #pragma omp for +#endif + + for(int row = 7; row < height - 7; row++) + for(int col = 7, indx = row * width + col; col < width - 7; col++, indx++) { + red [row][col] = CLIP(rgb[1][indx] - 65535.f * chr[0][indx]); + green[row][col] = CLIP(rgb[1][indx]); + blue [row][col] = CLIP(rgb[1][indx] - 65535.f * chr[1][indx]); + } + }// End of parallelization + + if (plistener) { + plistener->setProgress (1.0); + } + + free(chrarray); + free(rgbarray); + free(vdif); + free(hdif); +} +#endif + + +/* + Adaptive Homogeneity-Directed interpolation is based on + the work of Keigo Hirakawa, Thomas Parks, and Paul Lee. + */ +#define TS 256 /* Tile Size */ +#define FORC(cnt) for (c=0; c < cnt; c++) +#define FORC3 FORC(3) + +void RawImageSource::ahd_demosaic() +{ + int i, j, k, top, left, row, col, tr, tc, c, d, val, hm[2]; + float (*pix)[4], (*rix)[3]; + static const int dir[4] = { -1, 1, -TS, TS }; + float ldiff[2][4], abdiff[2][4], leps, abeps; + float xyz[3], xyz_cam[3][4]; + float* cbrt; + float (*rgb)[TS][TS][3]; + float (*lab)[TS][TS][3]; + float (*lix)[3]; + char (*homo)[TS][TS], *buffer; + double r; + + int width = W, height = H; + float (*image)[4]; + unsigned int colors = 3; + + const double xyz_rgb[3][3] = { /* XYZ from RGB */ + { 0.412453, 0.357580, 0.180423 }, + { 0.212671, 0.715160, 0.072169 }, + { 0.019334, 0.119193, 0.950227 } + }; + + const float d65_white[3] = { 0.950456, 1, 1.088754 }; + + if (plistener) { + plistener->setProgressStr (Glib::ustring::compose(M("TP_RAW_DMETHOD_PROGRESSBAR"), RAWParams::BayerSensor::getMethodString(RAWParams::BayerSensor::Method::AHD))); + plistener->setProgress (0.0); + } + + image = (float (*)[4]) calloc (H * W, sizeof * image); + + for (int ii = 0; ii < H; ii++) + for (int jj = 0; jj < W; jj++) { + image[ii * W + jj][fc(ii, jj)] = rawData[ii][jj]; + } + + cbrt = (float (*)) calloc (0x10000, sizeof * cbrt); + + for (i = 0; i < 0x10000; i++) { + r = (double)i / 65535.0; + cbrt[i] = r > 0.008856 ? std::cbrt(r) : 7.787 * r + 16 / 116.0; + } + + for (i = 0; i < 3; i++) + for (unsigned int j = 0; j < colors; j++) + for (xyz_cam[i][j] = k = 0; k < 3; k++) { + xyz_cam[i][j] += xyz_rgb[i][k] * imatrices.rgb_cam[k][j] / d65_white[i]; + } + + border_interpolate(5, image); + buffer = (char *) malloc (13 * TS * TS * sizeof(float)); /* 1664 kB */ + //merror (buffer, "ahd_interpolate()"); + rgb = (float(*)[TS][TS][3]) buffer; + lab = (float(*)[TS][TS][3])(buffer + 6 * TS * TS * sizeof(float)); + homo = (char (*)[TS][TS]) (buffer + 12 * TS * TS * sizeof(float)); + + // helper variables for progress indication + int n_tiles = ((height - 7 + (TS - 7)) / (TS - 6)) * ((width - 7 + (TS - 7)) / (TS - 6)); + int tile = 0; + + for (top = 2; top < height - 5; top += TS - 6) + for (left = 2; left < width - 5; left += TS - 6) { + /* Interpolate green horizontally and vertically: */ + for (row = top; row < top + TS && row < height - 2; row++) { + col = left + (FC(row, left) & 1); + + for (c = FC(row, col); col < left + TS && col < width - 2; col += 2) { + pix = image + (row * width + col); + val = 0.25 * ((pix[-1][1] + pix[0][c] + pix[1][1]) * 2 + - pix[-2][c] - pix[2][c]) ; + rgb[0][row - top][col - left][1] = median(static_cast(val), pix[-1][1], pix[1][1]); + val = 0.25 * ((pix[-width][1] + pix[0][c] + pix[width][1]) * 2 + - pix[-2 * width][c] - pix[2 * width][c]) ; + rgb[1][row - top][col - left][1] = median(static_cast(val), pix[-width][1], pix[width][1]); + } + } + + /* Interpolate red and blue, and convert to CIELab: */ + for (d = 0; d < 2; d++) + for (row = top + 1; row < top + TS - 1 && row < height - 3; row++) + for (col = left + 1; col < left + TS - 1 && col < width - 3; col++) { + pix = image + (row * width + col); + rix = &rgb[d][row - top][col - left]; + lix = &lab[d][row - top][col - left]; + + if ((c = 2 - FC(row, col)) == 1) { + c = FC(row + 1, col); + val = pix[0][1] + (0.5 * ( pix[-1][2 - c] + pix[1][2 - c] + - rix[-1][1] - rix[1][1] ) ); + rix[0][2 - c] = CLIP(val); + val = pix[0][1] + (0.5 * ( pix[-width][c] + pix[width][c] + - rix[-TS][1] - rix[TS][1] ) ); + } else + val = rix[0][1] + (0.25 * ( pix[-width - 1][c] + pix[-width + 1][c] + + pix[+width - 1][c] + pix[+width + 1][c] + - rix[-TS - 1][1] - rix[-TS + 1][1] + - rix[+TS - 1][1] - rix[+TS + 1][1]) ); + + rix[0][c] = CLIP(val); + c = FC(row, col); + rix[0][c] = pix[0][c]; + xyz[0] = xyz[1] = xyz[2] = 0.0; + FORCC { + xyz[0] += xyz_cam[0][c] * rix[0][c]; + xyz[1] += xyz_cam[1][c] * rix[0][c]; + xyz[2] += xyz_cam[2][c] * rix[0][c]; + } + + xyz[0] = CurveFactory::flinterp(cbrt, xyz[0]); + xyz[1] = CurveFactory::flinterp(cbrt, xyz[1]); + xyz[2] = CurveFactory::flinterp(cbrt, xyz[2]); + + //xyz[0] = xyz[0] > 0.008856 ? pow(xyz[0]/65535,1/3.0) : 7.787*xyz[0] + 16/116.0; + //xyz[1] = xyz[1] > 0.008856 ? pow(xyz[1]/65535,1/3.0) : 7.787*xyz[1] + 16/116.0; + //xyz[2] = xyz[2] > 0.008856 ? pow(xyz[2]/65535,1/3.0) : 7.787*xyz[2] + 16/116.0; + + lix[0][0] = (116 * xyz[1] - 16); + lix[0][1] = 500 * (xyz[0] - xyz[1]); + lix[0][2] = 200 * (xyz[1] - xyz[2]); + } + + /* Build homogeneity maps from the CIELab images: */ + memset (homo, 0, 2 * TS * TS); + + for (row = top + 2; row < top + TS - 2 && row < height - 4; row++) { + tr = row - top; + + for (col = left + 2; col < left + TS - 2 && col < width - 4; col++) { + tc = col - left; + + for (d = 0; d < 2; d++) { + lix = &lab[d][tr][tc]; + + for (i = 0; i < 4; i++) { + ldiff[d][i] = ABS(lix[0][0] - lix[dir[i]][0]); + abdiff[d][i] = SQR(lix[0][1] - lix[dir[i]][1]) + + SQR(lix[0][2] - lix[dir[i]][2]); + } + } + + leps = min(max(ldiff[0][0], ldiff[0][1]), + max(ldiff[1][2], ldiff[1][3])); + abeps = min(max(abdiff[0][0], abdiff[0][1]), + max(abdiff[1][2], abdiff[1][3])); + + for (d = 0; d < 2; d++) + for (i = 0; i < 4; i++) + if (ldiff[d][i] <= leps && abdiff[d][i] <= abeps) { + homo[d][tr][tc]++; + } + } + } + + /* Combine the most homogenous pixels for the final result: */ + for (row = top + 3; row < top + TS - 3 && row < height - 5; row++) { + tr = row - top; + + for (col = left + 3; col < left + TS - 3 && col < width - 5; col++) { + tc = col - left; + + for (d = 0; d < 2; d++) + for (hm[d] = 0, i = tr - 1; i <= tr + 1; i++) + for (j = tc - 1; j <= tc + 1; j++) { + hm[d] += homo[d][i][j]; + } + + if (hm[0] != hm[1]) { + FORC3 image[row * width + col][c] = rgb[hm[1] > hm[0]][tr][tc][c]; + } else + FORC3 image[row * width + col][c] = + 0.5 * (rgb[0][tr][tc][c] + rgb[1][tr][tc][c]) ; + } + } + + tile++; + + if(plistener) { + plistener->setProgress((double)tile / n_tiles); + } + } + + if(plistener) { + plistener->setProgress (1.0); + } + + free (buffer); + + for (int i = 0; i < H; i++) { + for (int j = 0; j < W; j++) { + red[i][j] = image[i * W + j][0]; + green[i][j] = image[i * W + j][1]; + blue[i][j] = image[i * W + j][2]; + } + } + + free (image); + free (cbrt); +} +#undef TS + +void RawImageSource::nodemosaic(bool bw) +{ + red(W, H); + green(W, H); + blue(W, H); + #pragma omp parallel for + + for (int i = 0; i < H; i++) { + for (int j = 0; j < W; j++) { + if (bw) { + red[i][j] = green[i][j] = blue[i][j] = rawData[i][j]; + } else if(ri->getSensorType() != ST_FUJI_XTRANS) { + switch( FC(i, j)) { + case 0: + red[i][j] = rawData[i][j]; + green[i][j] = blue[i][j] = 0; + break; + + case 1: + green[i][j] = rawData[i][j]; + red[i][j] = blue[i][j] = 0; + break; + + case 2: + blue[i][j] = rawData[i][j]; + red[i][j] = green[i][j] = 0; + break; + } + } else { + switch( ri->XTRANSFC(i, j)) { + case 0: + red[i][j] = rawData[i][j]; + green[i][j] = blue[i][j] = 0; + break; + + case 1: + green[i][j] = rawData[i][j]; + red[i][j] = blue[i][j] = 0; + break; + + case 2: + blue[i][j] = rawData[i][j]; + red[i][j] = green[i][j] = 0; + break; + } + } + } + } +} + +/* + Refinement based on EECI demosaicing algorithm by L. Chang and Y.P. Tan + Paul Lee + Adapted for RawTherapee - Jacques Desmis 04/2013 +*/ + +#ifdef __SSE2__ +#define CLIPV(a) LIMV(a,ZEROV,c65535v) +#endif +void RawImageSource::refinement(int PassCount) +{ + MyTime t1e, t2e; + t1e.set(); + + int width = W; + int height = H; + int w1 = width; + int w2 = 2 * w1; + + if (plistener) { + plistener->setProgressStr (M("TP_RAW_DMETHOD_PROGRESSBAR_REFINE")); + } + + array2D *rgb[3]; + rgb[0] = &red; + rgb[1] = &green; + rgb[2] = &blue; + + for (int b = 0; b < PassCount; b++) { + if (plistener) { + plistener->setProgress ((float)b / PassCount); + } + + +#ifdef _OPENMP + #pragma omp parallel +#endif + { + float *pix[3]; + + /* Reinforce interpolated green pixels on RED/BLUE pixel locations */ +#ifdef _OPENMP + #pragma omp for +#endif + + for (int row = 2; row < height - 2; row++) { + int col = 2 + (FC(row, 2) & 1); + int c = FC(row, col); +#ifdef __SSE2__ + __m128 dLv, dRv, dUv, dDv, v0v; + __m128 onev = _mm_set1_ps(1.f); + __m128 zd5v = _mm_set1_ps(0.5f); + __m128 c65535v = _mm_set1_ps(65535.f); + + for (; col < width - 8; col += 8) { + int indx = row * width + col; + pix[c] = (float*)(*rgb[c]) + indx; + pix[1] = (float*)(*rgb[1]) + indx; + dLv = onev / (onev + vabsf(LC2VFU(pix[c][ -2]) - LC2VFU(pix[c][0])) + vabsf(LC2VFU(pix[1][ 1]) - LC2VFU(pix[1][ -1]))); + dRv = onev / (onev + vabsf(LC2VFU(pix[c][ 2]) - LC2VFU(pix[c][0])) + vabsf(LC2VFU(pix[1][ 1]) - LC2VFU(pix[1][ -1]))); + dUv = onev / (onev + vabsf(LC2VFU(pix[c][-w2]) - LC2VFU(pix[c][0])) + vabsf(LC2VFU(pix[1][w1]) - LC2VFU(pix[1][-w1]))); + dDv = onev / (onev + vabsf(LC2VFU(pix[c][ w2]) - LC2VFU(pix[c][0])) + vabsf(LC2VFU(pix[1][w1]) - LC2VFU(pix[1][-w1]))); + v0v = CLIPV(LC2VFU(pix[c][0]) + zd5v + ((LC2VFU(pix[1][-1]) - LC2VFU(pix[c][-1])) * dLv + (LC2VFU(pix[1][1]) - LC2VFU(pix[c][1])) * dRv + (LC2VFU(pix[1][-w1]) - LC2VFU(pix[c][-w1])) * dUv + (LC2VFU(pix[1][w1]) - LC2VFU(pix[c][w1])) * dDv ) / (dLv + dRv + dUv + dDv)); + STC2VFU(pix[1][0], v0v); + } + +#endif + + for (; col < width - 2; col += 2) { + int indx = row * width + col; + pix[c] = (float*)(*rgb[c]) + indx; + pix[1] = (float*)(*rgb[1]) + indx; + float dL = 1.f / (1.f + fabsf(pix[c][ -2] - pix[c][0]) + fabsf(pix[1][ 1] - pix[1][ -1])); + float dR = 1.f / (1.f + fabsf(pix[c][ 2] - pix[c][0]) + fabsf(pix[1][ 1] - pix[1][ -1])); + float dU = 1.f / (1.f + fabsf(pix[c][-w2] - pix[c][0]) + fabsf(pix[1][w1] - pix[1][-w1])); + float dD = 1.f / (1.f + fabsf(pix[c][ w2] - pix[c][0]) + fabsf(pix[1][w1] - pix[1][-w1])); + float v0 = (pix[c][0] + 0.5f + ((pix[1][ -1] - pix[c][ -1]) * dL + (pix[1][ 1] - pix[c][ 1]) * dR + (pix[1][-w1] - pix[c][-w1]) * dU + (pix[1][ w1] - pix[c][ w1]) * dD ) / (dL + dR + dU + dD)); + pix[1][0] = CLIP(v0); + } + } + + /* Reinforce interpolated red/blue pixels on GREEN pixel locations */ +#ifdef _OPENMP + #pragma omp for +#endif + + for (int row = 2; row < height - 2; row++) { + int col = 2 + (FC(row, 3) & 1); + int c = FC(row, col + 1); +#ifdef __SSE2__ + __m128 dLv, dRv, dUv, dDv, v0v; + __m128 onev = _mm_set1_ps(1.f); + __m128 zd5v = _mm_set1_ps(0.5f); + __m128 c65535v = _mm_set1_ps(65535.f); + + for (; col < width - 8; col += 8) { + int indx = row * width + col; + pix[1] = (float*)(*rgb[1]) + indx; + + for (int i = 0; i < 2; c = 2 - c, i++) { + pix[c] = (float*)(*rgb[c]) + indx; + dLv = onev / (onev + vabsf(LC2VFU(pix[1][ -2]) - LC2VFU(pix[1][0])) + vabsf(LC2VFU(pix[c][ 1]) - LC2VFU(pix[c][ -1]))); + dRv = onev / (onev + vabsf(LC2VFU(pix[1][ 2]) - LC2VFU(pix[1][0])) + vabsf(LC2VFU(pix[c][ 1]) - LC2VFU(pix[c][ -1]))); + dUv = onev / (onev + vabsf(LC2VFU(pix[1][-w2]) - LC2VFU(pix[1][0])) + vabsf(LC2VFU(pix[c][w1]) - LC2VFU(pix[c][-w1]))); + dDv = onev / (onev + vabsf(LC2VFU(pix[1][ w2]) - LC2VFU(pix[1][0])) + vabsf(LC2VFU(pix[c][w1]) - LC2VFU(pix[c][-w1]))); + v0v = CLIPV(LC2VFU(pix[1][0]) + zd5v - ((LC2VFU(pix[1][-1]) - LC2VFU(pix[c][-1])) * dLv + (LC2VFU(pix[1][1]) - LC2VFU(pix[c][1])) * dRv + (LC2VFU(pix[1][-w1]) - LC2VFU(pix[c][-w1])) * dUv + (LC2VFU(pix[1][w1]) - LC2VFU(pix[c][w1])) * dDv ) / (dLv + dRv + dUv + dDv)); + STC2VFU(pix[c][0], v0v); + } + } + +#endif + + for (; col < width - 2; col += 2) { + int indx = row * width + col; + pix[1] = (float*)(*rgb[1]) + indx; + + for (int i = 0; i < 2; c = 2 - c, i++) { + pix[c] = (float*)(*rgb[c]) + indx; + float dL = 1.f / (1.f + fabsf(pix[1][ -2] - pix[1][0]) + fabsf(pix[c][ 1] - pix[c][ -1])); + float dR = 1.f / (1.f + fabsf(pix[1][ 2] - pix[1][0]) + fabsf(pix[c][ 1] - pix[c][ -1])); + float dU = 1.f / (1.f + fabsf(pix[1][-w2] - pix[1][0]) + fabsf(pix[c][w1] - pix[c][-w1])); + float dD = 1.f / (1.f + fabsf(pix[1][ w2] - pix[1][0]) + fabsf(pix[c][w1] - pix[c][-w1])); + float v0 = (pix[1][0] + 0.5f - ((pix[1][ -1] - pix[c][ -1]) * dL + (pix[1][ 1] - pix[c][ 1]) * dR + (pix[1][-w1] - pix[c][-w1]) * dU + (pix[1][ w1] - pix[c][ w1]) * dD ) / (dL + dR + dU + dD)); + pix[c][0] = CLIP(v0); + } + } + } + + /* Reinforce integrated red/blue pixels on BLUE/RED pixel locations */ +#ifdef _OPENMP + #pragma omp for +#endif + + for (int row = 2; row < height - 2; row++) { + int col = 2 + (FC(row, 2) & 1); + int c = 2 - FC(row, col); +#ifdef __SSE2__ + __m128 dLv, dRv, dUv, dDv, v0v; + __m128 onev = _mm_set1_ps(1.f); + __m128 zd5v = _mm_set1_ps(0.5f); + __m128 c65535v = _mm_set1_ps(65535.f); + + for (; col < width - 8; col += 8) { + int indx = row * width + col; + pix[0] = (float*)(*rgb[0]) + indx; + pix[1] = (float*)(*rgb[1]) + indx; + pix[2] = (float*)(*rgb[2]) + indx; + int d = 2 - c; + dLv = onev / (onev + vabsf(LC2VFU(pix[d][ -2]) - LC2VFU(pix[d][0])) + vabsf(LC2VFU(pix[1][ 1]) - LC2VFU(pix[1][ -1]))); + dRv = onev / (onev + vabsf(LC2VFU(pix[d][ 2]) - LC2VFU(pix[d][0])) + vabsf(LC2VFU(pix[1][ 1]) - LC2VFU(pix[1][ -1]))); + dUv = onev / (onev + vabsf(LC2VFU(pix[d][-w2]) - LC2VFU(pix[d][0])) + vabsf(LC2VFU(pix[1][w1]) - LC2VFU(pix[1][-w1]))); + dDv = onev / (onev + vabsf(LC2VFU(pix[d][ w2]) - LC2VFU(pix[d][0])) + vabsf(LC2VFU(pix[1][w1]) - LC2VFU(pix[1][-w1]))); + v0v = CLIPV(LC2VFU(pix[1][0]) + zd5v - ((LC2VFU(pix[1][-1]) - LC2VFU(pix[c][-1])) * dLv + (LC2VFU(pix[1][1]) - LC2VFU(pix[c][1])) * dRv + (LC2VFU(pix[1][-w1]) - LC2VFU(pix[c][-w1])) * dUv + (LC2VFU(pix[1][w1]) - LC2VFU(pix[c][w1])) * dDv ) / (dLv + dRv + dUv + dDv)); + STC2VFU(pix[c][0], v0v); + } + +#endif + + for (; col < width - 2; col += 2) { + int indx = row * width + col; + pix[0] = (float*)(*rgb[0]) + indx; + pix[1] = (float*)(*rgb[1]) + indx; + pix[2] = (float*)(*rgb[2]) + indx; + int d = 2 - c; + float dL = 1.f / (1.f + fabsf(pix[d][ -2] - pix[d][0]) + fabsf(pix[1][ 1] - pix[1][ -1])); + float dR = 1.f / (1.f + fabsf(pix[d][ 2] - pix[d][0]) + fabsf(pix[1][ 1] - pix[1][ -1])); + float dU = 1.f / (1.f + fabsf(pix[d][-w2] - pix[d][0]) + fabsf(pix[1][w1] - pix[1][-w1])); + float dD = 1.f / (1.f + fabsf(pix[d][ w2] - pix[d][0]) + fabsf(pix[1][w1] - pix[1][-w1])); + float v0 = (pix[1][0] + 0.5f - ((pix[1][ -1] - pix[c][ -1]) * dL + (pix[1][ 1] - pix[c][ 1]) * dR + (pix[1][-w1] - pix[c][-w1]) * dU + (pix[1][ w1] - pix[c][ w1]) * dD ) / (dL + dR + dU + dD)); + pix[c][0] = CLIP(v0); + } + } + } // end parallel + } + + t2e.set(); + + if (settings->verbose) { + printf("Refinement Lee %d usec\n", t2e.etime(t1e)); + } +} +#ifdef __SSE2__ +#undef CLIPV +#endif + + +// Refinement based on EECI demozaicing algorithm by L. Chang and Y.P. Tan +// from "Lassus" : Luis Sanz Rodriguez, adapted by Jacques Desmis - JDC - and Oliver Duis for RawTherapee +// increases the signal to noise ratio (PSNR) # +1 to +2 dB : tested with Dcraw : eg: Lighthouse + AMaZE : whitout refinement:39.96dB, with refinement:41.86 dB +// reduce color artifacts, improves the interpolation +// but it's relatively slow +// +// Should be DISABLED if it decreases image quality by increases some image noise and generates blocky edges +void RawImageSource::refinement_lassus(int PassCount) +{ + // const int PassCount=1; + + // if (settings->verbose) printf("Refinement\n"); + + MyTime t1e, t2e; + t1e.set(); + int u = W, v = 2 * u, w = 3 * u, x = 4 * u, y = 5 * u; + float (*image)[3]; + image = (float(*)[3]) calloc(W * H, sizeof * image); +#ifdef _OPENMP + #pragma omp parallel shared(image) +#endif + { + // convert red, blue, green to image +#ifdef _OPENMP + #pragma omp for +#endif + + for (int i = 0; i < H; i++) { + for (int j = 0; j < W; j++) { + image[i * W + j][0] = red [i][j]; + image[i * W + j][1] = green[i][j]; + image[i * W + j][2] = blue [i][j]; + } + } + + for (int b = 0; b < PassCount; b++) { + if (plistener) { + plistener->setProgressStr (M("TP_RAW_DMETHOD_PROGRESSBAR_REFINE")); + plistener->setProgress ((float)b / PassCount); + } + + // Reinforce interpolated green pixels on RED/BLUE pixel locations +#ifdef _OPENMP + #pragma omp for +#endif + + for (int row = 6; row < H - 6; row++) { + for (int col = 6 + (FC(row, 2) & 1), c = FC(row, col); col < W - 6; col += 2) { + float (*pix)[3] = image + row * W + col; + + // Cubic Spline Interpolation by Li and Randhawa, modified by Luis Sanz Rodriguez + + float f[4]; + f[0] = 1.0f / (1.0f + xmul2f(fabs(x1125(pix[-v][c]) - x0875(pix[0][c]) - x0250(pix[-x][c]))) + fabs(x0875(pix[u][1]) - x1125(pix[-u][1]) + x0250(pix[-w][1])) + fabs(x0875(pix[-w][1]) - x1125(pix[-u][1]) + x0250(pix[-y][1]))); + f[1] = 1.0f / (1.0f + xmul2f(fabs(x1125(pix[+2][c]) - x0875(pix[0][c]) - x0250(pix[+4][c]))) + fabs(x0875(pix[1][1]) - x1125(pix[-1][1]) + x0250(pix[+3][1])) + fabs(x0875(pix[+3][1]) - x1125(pix[+1][1]) + x0250(pix[+5][1]))); + f[2] = 1.0f / (1.0f + xmul2f(fabs(x1125(pix[-2][c]) - x0875(pix[0][c]) - x0250(pix[-4][c]))) + fabs(x0875(pix[1][1]) - x1125(pix[-1][1]) + x0250(pix[-3][1])) + fabs(x0875(pix[-3][1]) - x1125(pix[-1][1]) + x0250(pix[-5][1]))); + f[3] = 1.0f / (1.0f + xmul2f(fabs(x1125(pix[+v][c]) - x0875(pix[0][c]) - x0250(pix[+x][c]))) + fabs(x0875(pix[u][1]) - x1125(pix[-u][1]) + x0250(pix[+w][1])) + fabs(x0875(pix[+w][1]) - x1125(pix[+u][1]) + x0250(pix[+y][1]))); + + float g[4];//CLIREF avoid overflow + g[0] = pix[0][c] + (x0875(CLIREF(pix[-u][1] - pix[-u][c])) + x0125(CLIREF(pix[+u][1] - pix[+u][c]))); + g[1] = pix[0][c] + (x0875(CLIREF(pix[+1][1] - pix[+1][c])) + x0125(CLIREF(pix[-1][1] - pix[-1][c]))); + g[2] = pix[0][c] + (x0875(CLIREF(pix[-1][1] - pix[-1][c])) + x0125(CLIREF(pix[+1][1] - pix[+1][c]))); + g[3] = pix[0][c] + (x0875(CLIREF(pix[+u][1] - pix[+u][c])) + x0125(CLIREF(pix[-u][1] - pix[-u][c]))); + + pix[0][1] = (f[0] * g[0] + f[1] * g[1] + f[2] * g[2] + f[3] * g[3]) / (f[0] + f[1] + f[2] + f[3]); + + } + } + + // Reinforce interpolated red/blue pixels on GREEN pixel locations +#ifdef _OPENMP + #pragma omp for +#endif + + for (int row = 6; row < H - 6; row++) { + for (int col = 6 + (FC(row, 3) & 1), c = FC(row, col + 1); col < W - 6; col += 2) { + float (*pix)[3] = image + row * W + col; + + for (int i = 0; i < 2; c = 2 - c, i++) { + float f[4]; + f[0] = 1.0f / (1.0f + xmul2f(fabs(x0875(pix[-v][1]) - x1125(pix[0][1]) + x0250(pix[-x][1]))) + fabs(pix[u] [c] - pix[-u][c]) + fabs(pix[-w][c] - pix[-u][c])); + f[1] = 1.0f / (1.0f + xmul2f(fabs(x0875(pix[+2][1]) - x1125(pix[0][1]) + x0250(pix[+4][1]))) + fabs(pix[+1][c] - pix[-1][c]) + fabs(pix[+3][c] - pix[+1][c])); + f[2] = 1.0f / (1.0f + xmul2f(fabs(x0875(pix[-2][1]) - x1125(pix[0][1]) + x0250(pix[-4][1]))) + fabs(pix[+1][c] - pix[-1][c]) + fabs(pix[-3][c] - pix[-1][c])); + f[3] = 1.0f / (1.0f + xmul2f(fabs(x0875(pix[+v][1]) - x1125(pix[0][1]) + x0250(pix[+x][1]))) + fabs(pix[u] [c] - pix[-u][c]) + fabs(pix[+w][c] - pix[+u][c])); + + float g[5];//CLIREF avoid overflow + g[0] = CLIREF(pix[-u][1] - pix[-u][c]); + g[1] = CLIREF(pix[+1][1] - pix[+1][c]); + g[2] = CLIREF(pix[-1][1] - pix[-1][c]); + g[3] = CLIREF(pix[+u][1] - pix[+u][c]); + g[4] = ((f[0] * g[0] + f[1] * g[1] + f[2] * g[2] + f[3] * g[3]) / (f[0] + f[1] + f[2] + f[3])); + pix[0][c] = pix[0][1] - (0.65f * g[4] + 0.35f * CLIREF(pix[0][1] - pix[0][c])); + } + } + } + + // Reinforce integrated red/blue pixels on BLUE/RED pixel locations +#ifdef _OPENMP + #pragma omp for +#endif + + for (int row = 6; row < H - 6; row++) { + for (int col = 6 + (FC(row, 2) & 1), c = 2 - FC(row, col), d = 2 - c; col < W - 6; col += 2) { + float (*pix)[3] = image + row * W + col; + + float f[4]; + f[0] = 1.0f / (1.0f + xmul2f(fabs(x1125(pix[-v][d]) - x0875(pix[0][d]) - x0250(pix[-x][d]))) + fabs(x0875(pix[u][1]) - x1125(pix[-u][1]) + x0250(pix[-w][1])) + fabs(x0875(pix[-w][1]) - x1125(pix[-u][1]) + x0250(pix[-y][1]))); + f[1] = 1.0f / (1.0f + xmul2f(fabs(x1125(pix[+2][d]) - x0875(pix[0][d]) - x0250(pix[+4][d]))) + fabs(x0875(pix[1][1]) - x1125(pix[-1][1]) + x0250(pix[+3][1])) + fabs(x0875(pix[+3][1]) - x1125(pix[+1][1]) + x0250(pix[+5][1]))); + f[2] = 1.0f / (1.0f + xmul2f(fabs(x1125(pix[-2][d]) - x0875(pix[0][d]) - x0250(pix[-4][d]))) + fabs(x0875(pix[1][1]) - x1125(pix[-1][1]) + x0250(pix[-3][1])) + fabs(x0875(pix[-3][1]) - x1125(pix[-1][1]) + x0250(pix[-5][1]))); + f[3] = 1.0f / (1.0f + xmul2f(fabs(x1125(pix[+v][d]) - x0875(pix[0][d]) - x0250(pix[+x][d]))) + fabs(x0875(pix[u][1]) - x1125(pix[-u][1]) + x0250(pix[+w][1])) + fabs(x0875(pix[+w][1]) - x1125(pix[+u][1]) + x0250(pix[+y][1]))); + + float g[5]; + g[0] = (x0875((pix[-u][1] - pix[-u][c])) + x0125((pix[-v][1] - pix[-v][c]))); + g[1] = (x0875((pix[+1][1] - pix[+1][c])) + x0125((pix[+2][1] - pix[+2][c]))); + g[2] = (x0875((pix[-1][1] - pix[-1][c])) + x0125((pix[-2][1] - pix[-2][c]))); + g[3] = (x0875((pix[+u][1] - pix[+u][c])) + x0125((pix[+v][1] - pix[+v][c]))); + + g[4] = (f[0] * g[0] + f[1] * g[1] + f[2] * g[2] + f[3] * g[3]) / (f[0] + f[1] + f[2] + f[3]); + + const std::array p = { + pix[-u - 1][1] - pix[-u - 1][c], + pix[-u + 0][1] - pix[-u + 0][c], + pix[-u + 1][1] - pix[-u + 1][c], + pix[+0 - 1][1] - pix[+0 - 1][c], + pix[+0 + 0][1] - pix[+0 + 0][c], + pix[+0 + 1][1] - pix[+0 + 1][c], + pix[+u - 1][1] - pix[+u - 1][c], + pix[+u + 0][1] - pix[+u + 0][c], + pix[+u + 1][1] - pix[+u + 1][c] + }; + + const float med = median(p); + + pix[0][c] = LIM(pix[0][1] - (1.30f * g[4] - 0.30f * (pix[0][1] - pix[0][c])), 0.99f * (pix[0][1] - med), 1.01f * (pix[0][1] - med)); + + } + } + + } + + // put modified values to red, green, blue +#ifdef _OPENMP + #pragma omp for +#endif + + for (int i = 0; i < H; i++) { + for (int j = 0; j < W; j++) { + red [i][j] = image[i * W + j][0]; + green[i][j] = image[i * W + j][1]; + blue [i][j] = image[i * W + j][2]; + } + } + } + + free(image); + + t2e.set(); + + if (settings->verbose) { + printf("Refinement Lassus %d usec\n", t2e.etime(t1e)); + } +} + + +/* + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the author nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// If you want to use the code, you need to display name of the original authors in +// your software! + +/* DCB demosaicing by Jacek Gozdz (cuniek@kft.umcs.lublin.pl) + * the code is open source (BSD licence) +*/ + +#define TILESIZE 192 +#define TILEBORDER 10 +#define CACHESIZE (TILESIZE+2*TILEBORDER) + +inline void RawImageSource::dcb_initTileLimits(int &colMin, int &rowMin, int &colMax, int &rowMax, int x0, int y0, int border) +{ + rowMin = border; + colMin = border; + rowMax = CACHESIZE - border; + colMax = CACHESIZE - border; + + if(!y0 ) { + rowMin = TILEBORDER + border; + } + + if(!x0 ) { + colMin = TILEBORDER + border; + } + + if( y0 + TILESIZE + TILEBORDER >= H - border) { + rowMax = TILEBORDER + H - border - y0; + } + + if( x0 + TILESIZE + TILEBORDER >= W - border) { + colMax = TILEBORDER + W - border - x0; + } +} + +void RawImageSource::fill_raw( float (*cache )[3], int x0, int y0, float** rawData) +{ + int rowMin, colMin, rowMax, colMax; + dcb_initTileLimits(colMin, rowMin, colMax, rowMax, x0, y0, 0); + + for (int row = rowMin, y = y0 - TILEBORDER + rowMin; row < rowMax; row++, y++) + for (int col = colMin, x = x0 - TILEBORDER + colMin, indx = row * CACHESIZE + col; col < colMax; col++, x++, indx++) { + cache[indx][fc(y, x)] = rawData[y][x]; + } +} + +void RawImageSource::fill_border( float (*cache )[3], int border, int x0, int y0) +{ + unsigned f; + float sum[8]; + constexpr unsigned int colors = 3; // used in FORCC + + for (int row = y0; row < y0 + TILESIZE + TILEBORDER && row < H; row++) { + for (int col = x0; col < x0 + TILESIZE + TILEBORDER && col < W; col++) { + if (col >= border && col < W - border && row >= border && row < H - border) { + col = W - border; + + if(col >= x0 + TILESIZE + TILEBORDER ) { + break; + } + } + + memset(sum, 0, sizeof sum); + + for (int y = row - 1; y != row + 2; y++) + for (int x = col - 1; x != col + 2; x++) + if (y < H && y < y0 + TILESIZE + TILEBORDER && x < W && x < x0 + TILESIZE + TILEBORDER) { + f = fc(y, x); + sum[f] += cache[(y - y0 + TILEBORDER) * CACHESIZE + TILEBORDER + x - x0][f]; + sum[f + 4]++; + } + + f = fc(row, col); + FORCC + + if (c != f && sum[c + 4] > 0) { + cache[(row - y0 + TILEBORDER) * CACHESIZE + TILEBORDER + col - x0][c] = sum[c] / sum[c + 4]; + } + } + } +} + +// saves red and blue + +// change buffer[3] -> buffer[2], possibly to buffer[1] if split +// into two loops, one for R and another for B, could also be smaller because +// there is no need for green pixels pass +// this would decrease the amount of needed memory +// from megapixels*2 records to megapixels*0.5 +// also don't know if float is needed as data is 1-65536 integer (I believe!!) +// comment from Ingo: float is needed because rawdata in rt is float +void RawImageSource::copy_to_buffer( float (*buffer)[2], float (*image)[3]) +{ + for (int indx = 0; indx < CACHESIZE * CACHESIZE; indx++) { + buffer[indx][0] = image[indx][0]; //R + buffer[indx][1] = image[indx][2]; //B + } +} + +// restores red and blue + +// other comments like in copy_to_buffer +void RawImageSource::restore_from_buffer(float (*image)[3], float (*buffer)[2]) +{ + for (int indx = 0; indx < CACHESIZE * CACHESIZE; indx++) { + image[indx][0] = buffer[indx][0]; //R + image[indx][2] = buffer[indx][1]; //B + } +} + +// First pass green interpolation + +// remove entirely: bufferH and bufferV +void RawImageSource::dcb_hid(float (*image)[3], int x0, int y0) +{ + const int u = CACHESIZE; + int rowMin, colMin, rowMax, colMax; + dcb_initTileLimits(colMin, rowMin, colMax, rowMax, x0, y0, 2); + +// simple green bilinear in R and B pixels + for (int row = rowMin; row < rowMax; row++) + for (int col = colMin + (FC(y0 - TILEBORDER + row, x0 - TILEBORDER + colMin) & 1), indx = row * CACHESIZE + col; col < colMax; col += 2, indx += 2) { + assert(indx - u - 1 >= 0 && indx + u + 1 < u * u); + + image[indx][1] = 0.25*(image[indx-1][1]+image[indx+1][1]+image[indx-u][1]+image[indx+u][1]); + } +} + +// missing colours are interpolated +void RawImageSource::dcb_color(float (*image)[3], int x0, int y0) +{ + const int u = CACHESIZE; + int rowMin, colMin, rowMax, colMax; + dcb_initTileLimits(colMin, rowMin, colMax, rowMax, x0, y0, 1); + + // red in blue pixel, blue in red pixel + for (int row = rowMin; row < rowMax; row++) + for (int col = colMin + (FC(y0 - TILEBORDER + row, x0 - TILEBORDER + colMin) & 1), indx = row * CACHESIZE + col, c = 2 - FC(y0 - TILEBORDER + row, x0 - TILEBORDER + col); col < colMax; col += 2, indx += 2) { + assert(indx >= 0 && indx < u * u && c >= 0 && c < 4); + + +//Jacek comment: one multiplication less + image[indx][c] = image[indx][1] + + ( image[indx + u + 1][c] + image[indx + u - 1][c] + image[indx - u + 1][c] + image[indx - u - 1][c] + - (image[indx + u + 1][1] + image[indx + u - 1][1] + image[indx - u + 1][1] + image[indx - u - 1][1]) ) * 0.25f; + +/* original + image[indx][c] = ( 4.f * image[indx][1] + - image[indx + u + 1][1] - image[indx + u - 1][1] - image[indx - u + 1][1] - image[indx - u - 1][1] + + image[indx + u + 1][c] + image[indx + u - 1][c] + image[indx - u + 1][c] + image[indx - u - 1][c] ) * 0.25f; +*/ + } + + // red or blue in green pixels + for (int row = rowMin; row < rowMax; row++) + for (int col = colMin + (FC(y0 - TILEBORDER + row, x0 - TILEBORDER + colMin + 1) & 1), indx = row * CACHESIZE + col, c = FC(y0 - TILEBORDER + row, x0 - TILEBORDER + col + 1), d = 2 - c; col < colMax; col += 2, indx += 2) { + assert(indx >= 0 && indx < u * u && c >= 0 && c < 4); + +//Jacek comment: two multiplications (in total) less + image[indx][c] = image[indx][1] + (image[indx + 1][c] + image[indx - 1][c] - (image[indx + 1][1] + image[indx - 1][1])) * 0.5f; + image[indx][d] = image[indx][1] + (image[indx + u][d] + image[indx - u][d] - (image[indx + u][1] + image[indx - u][1])) * 0.5f; + + +/* original + image[indx][c] = (2.f * image[indx][1] - image[indx + 1][1] - image[indx - 1][1] + image[indx + 1][c] + image[indx - 1][c]) * 0.5f; + image[indx][d] = (2.f * image[indx][1] - image[indx + u][1] - image[indx - u][1] + image[indx + u][d] + image[indx - u][d]) * 0.5f; +*/ + } +} + +// green correction +void RawImageSource::dcb_hid2(float (*image)[3], int x0, int y0) +{ + const int v = 2 * CACHESIZE; + int rowMin, colMin, rowMax, colMax; + dcb_initTileLimits(colMin, rowMin, colMax, rowMax, x0, y0, 2); + + for (int row = rowMin; row < rowMax; row++) { + for (int col = colMin + (FC(y0 - TILEBORDER + row, x0 - TILEBORDER + colMin) & 1), indx = row * CACHESIZE + col, c = FC(y0 - TILEBORDER + row, x0 - TILEBORDER + col); col < colMax; col += 2, indx += 2) { + assert(indx - v >= 0 && indx + v < CACHESIZE * CACHESIZE); + +//Jacek comment: one multiplication less + image[indx][1] = image[indx][c] + + (image[indx + v][1] + image[indx - v][1] + image[indx - 2][1] + image[indx + 2][1] + - (image[indx + v][c] + image[indx - v][c] + image[indx - 2][c] + image[indx + 2][c])) * 0.25f; + +/* original + image[indx][1] = (image[indx + v][1] + image[indx - v][1] + image[indx - 2][1] + image[indx + 2][1]) * 0.25f + + image[indx][c] - ( image[indx + v][c] + image[indx - v][c] + image[indx - 2][c] + image[indx + 2][c]) * 0.25f; +*/ + } + } +} + +// green is used to create +// an interpolation direction map +// 1 = vertical +// 0 = horizontal +// saved in image[][3] + +// seems at least 2 persons implemented some code, as this one has different coding style, could be unified +// I don't know if *pix is faster than a loop working on image[] directly +void RawImageSource::dcb_map(float (*image)[3], uint8_t *map, int x0, int y0) +{ + const int u = 3 * CACHESIZE; + int rowMin, colMin, rowMax, colMax; + dcb_initTileLimits(colMin, rowMin, colMax, rowMax, x0, y0, 2); + + for (int row = rowMin; row < rowMax; row++) { + for (int col = colMin, indx = row * CACHESIZE + col; col < colMax; col++, indx++) { + float *pix = &(image[indx][1]); + + assert(indx >= 0 && indx < u * u); + + // comparing 4 * a to (b+c+d+e) instead of a to (b+c+d+e)/4 is faster because divisions are slow + if ( 4 * (*pix) > ( (pix[-3] + pix[+3]) + (pix[-u] + pix[+u])) ) { + map[indx] = ((min(pix[-3], pix[+3]) + (pix[-3] + pix[+3]) ) < (min(pix[-u], pix[+u]) + (pix[-u] + pix[+u]))); + } else { + map[indx] = ((max(pix[-3], pix[+3]) + (pix[-3] + pix[+3]) ) > (max(pix[-u], pix[+u]) + (pix[-u] + pix[+u]))); + } + } + } +} + +// interpolated green pixels are corrected using the map +void RawImageSource::dcb_correction(float (*image)[3], uint8_t *map, int x0, int y0) +{ + const int u = CACHESIZE, v = 2 * CACHESIZE; + int rowMin, colMin, rowMax, colMax; + dcb_initTileLimits(colMin, rowMin, colMax, rowMax, x0, y0, 2); + + for (int row = rowMin; row < rowMax; row++) { + for (int indx = row * CACHESIZE + colMin + (FC(y0 - TILEBORDER + row, x0 - TILEBORDER + colMin) & 1); indx < row * CACHESIZE + colMax; indx += 2) { +// for (int col = colMin + (FC(y0 - TILEBORDER + row, x0 - TILEBORDER + colMin) & 1), indx = row * CACHESIZE + col; col < colMax; col += 2, indx += 2) { + float current = 4 * map[indx] + + 2 * (map[indx + u] + map[indx - u] + map[indx + 1] + map[indx - 1]) + + map[indx + v] + map[indx - v] + map[indx + 2] + map[indx - 2]; + + assert(indx >= 0 && indx < u * u); + image[indx][1] = ((16.f - current) * (image[indx - 1][1] + image[indx + 1][1]) + current * (image[indx - u][1] + image[indx + u][1]) ) * 0.03125f; +// image[indx][1] = ((16.f - current) * (image[indx - 1][1] + image[indx + 1][1]) * 0.5f + current * (image[indx - u][1] + image[indx + u][1]) * 0.5f ) * 0.0625f; + } + } +} + +// R and B smoothing using green contrast, all pixels except 2 pixel wide border + +// again code with *pix, is this kind of calculating faster in C, than this what was commented? +void RawImageSource::dcb_pp(float (*image)[3], int x0, int y0) +{ + const int u = CACHESIZE; + int rowMin, colMin, rowMax, colMax; + dcb_initTileLimits(colMin, rowMin, colMax, rowMax, x0, y0, 2); + + for (int row = rowMin; row < rowMax; row++) + for (int col = colMin, indx = row * CACHESIZE + col; col < colMax; col++, indx++) { +// float r1 = image[indx-1][0] + image[indx+1][0] + image[indx-u][0] + image[indx+u][0] + image[indx-u-1][0] + image[indx+u+1][0] + image[indx-u+1][0] + image[indx+u-1][0]; +// float g1 = image[indx-1][1] + image[indx+1][1] + image[indx-u][1] + image[indx+u][1] + image[indx-u-1][1] + image[indx+u+1][1] + image[indx-u+1][1] + image[indx+u-1][1]; +// float b1 = image[indx-1][2] + image[indx+1][2] + image[indx-u][2] + image[indx+u][2] + image[indx-u-1][2] + image[indx+u+1][2] + image[indx-u+1][2] + image[indx+u-1][2]; + float (*pix)[3] = image + (indx - u - 1); + float r1 = (*pix)[0]; + float g1 = (*pix)[1]; + float b1 = (*pix)[2]; + pix++; + r1 += (*pix)[0]; + g1 += (*pix)[1]; + b1 += (*pix)[2]; + pix++; + r1 += (*pix)[0]; + g1 += (*pix)[1]; + b1 += (*pix)[2]; + pix += CACHESIZE - 2; + r1 += (*pix)[0]; + g1 += (*pix)[1]; + b1 += (*pix)[2]; + pix += 2; + r1 += (*pix)[0]; + g1 += (*pix)[1]; + b1 += (*pix)[2]; + pix += CACHESIZE - 2; + r1 += (*pix)[0]; + g1 += (*pix)[1]; + b1 += (*pix)[2]; + pix++; + r1 += (*pix)[0]; + g1 += (*pix)[1]; + b1 += (*pix)[2]; + pix++; + r1 += (*pix)[0]; + g1 += (*pix)[1]; + b1 += (*pix)[2]; + r1 *= 0.125f; + g1 *= 0.125f; + b1 *= 0.125f; + r1 += ( image[indx][1] - g1 ); + b1 += ( image[indx][1] - g1 ); + + assert(indx >= 0 && indx < u * u); + image[indx][0] = r1; + image[indx][2] = b1; + } +} + +// interpolated green pixels are corrected using the map +// with correction +void RawImageSource::dcb_correction2(float (*image)[3], uint8_t *map, int x0, int y0) +{ + const int u = CACHESIZE, v = 2 * CACHESIZE; + int rowMin, colMin, rowMax, colMax; + dcb_initTileLimits(colMin, rowMin, colMax, rowMax, x0, y0, 4); + + for (int row = rowMin; row < rowMax; row++) { + for (int indx = row * CACHESIZE + colMin + (FC(y0 - TILEBORDER + row, x0 - TILEBORDER + colMin) & 1), c = FC(y0 - TILEBORDER + row, x0 - TILEBORDER + colMin + (FC(y0 - TILEBORDER + row, x0 - TILEBORDER + colMin) & 1)); indx < row * CACHESIZE + colMax; indx += 2) { + // map values are uint8_t either 0 or 1. Adding them using integer instructions is perfectly valid and fast. Final result is converted to float then + float current = 4 * map[indx] + + 2 * (map[indx + u] + map[indx - u] + map[indx + 1] + map[indx - 1]) + + map[indx + v] + map[indx - v] + map[indx + 2] + map[indx - 2]; + + assert(indx >= 0 && indx < u * u); + +// Jacek comment: works now, and has 3 float mults and 9 float adds + image[indx][1] = image[indx][c] + + ((16.f - current) * (image[indx - 1][1] + image[indx + 1][1] - (image[indx + 2][c] + image[indx - 2][c])) + + current * (image[indx - u][1] + image[indx + u][1] - (image[indx + v][c] + image[indx - v][c]))) * 0.03125f; + + + // 4 float mults and 9 float adds + // Jacek comment: not mathematically identical to original +/* image[indx][1] = 16.f * image[indx][c] + + ((16.f - current) * ((image[indx - 1][1] + image[indx + 1][1]) + - (image[indx + 2][c] + image[indx - 2][c])) + + current * ((image[indx - u][1] + image[indx + u][1]) - (image[indx + v][c] + image[indx - v][c]))) * 0.03125f; +*/ + // 7 float mults and 10 float adds + // original code +/* + image[indx][1] = ((16.f - current) * ((image[indx - 1][1] + image[indx + 1][1]) * 0.5f + + image[indx][c] - (image[indx + 2][c] + image[indx - 2][c]) * 0.5f) + + current * ((image[indx - u][1] + image[indx + u][1]) * 0.5f + image[indx][c] - (image[indx + v][c] + image[indx - v][c]) * 0.5f)) * 0.0625f; +*/ + } + } +} + +// image refinement +void RawImageSource::dcb_refinement(float (*image)[3], uint8_t *map, int x0, int y0) +{ + const int u = CACHESIZE, v = 2 * CACHESIZE; + int rowMin, colMin, rowMax, colMax; + dcb_initTileLimits(colMin, rowMin, colMax, rowMax, x0, y0, 4); + + float f0, f1, f2, g1, h0, h1, h2, g2; + + for (int row = rowMin; row < rowMax; row++) + for (int col = colMin + (FC(y0 - TILEBORDER + row, x0 - TILEBORDER + colMin) & 1), indx = row * CACHESIZE + col, c = FC(y0 - TILEBORDER + row, x0 - TILEBORDER + col); col < colMax; col += 2, indx += 2) { + + float current = 4 * map[indx] + + 2 * (map[indx + u] + map[indx - u] + map[indx + 1] + map[indx - 1]) + + map[indx + v] + map[indx - v] + map[indx - 2] + map[indx + 2]; + + float currPix = image[indx][c]; + + f0 = (float)(image[indx - u][1] + image[indx + u][1]) / (1.f + 2.f * currPix); + f1 = 2.f * image[indx - u][1] / (1.f + image[indx - v][c] + currPix); + f2 = 2.f * image[indx + u][1] / (1.f + image[indx + v][c] + currPix); + + g1 = f0 + f1 + f2; + + h0 = (float)(image[indx - 1][1] + image[indx + 1][1]) / (1.f + 2.f * currPix); + h1 = 2.f * image[indx - 1][1] / (1.f + image[indx - 2][c] + currPix); + h2 = 2.f * image[indx + 1][1] / (1.f + image[indx + 2][c] + currPix); + + g2 = h0 + h1 + h2; + + // new green value + assert(indx >= 0 && indx < u * u); + currPix *= (current * g1 + (16.f - current) * g2) / 48.f; + + // get rid of the overshot pixels + float minVal = min(image[indx - 1][1], min(image[indx + 1][1], min(image[indx - u][1], image[indx + u][1]))); + float maxVal = max(image[indx - 1][1], max(image[indx + 1][1], max(image[indx - u][1], image[indx + u][1]))); + + image[indx][1] = LIM(currPix, minVal, maxVal); + + } +} + +// missing colours are interpolated using high quality algorithm by Luis Sanz Rodriguez +void RawImageSource::dcb_color_full(float (*image)[3], int x0, int y0, float (*chroma)[2]) +{ + const int u = CACHESIZE, w = 3 * CACHESIZE; + int rowMin, colMin, rowMax, colMax; + dcb_initTileLimits(colMin, rowMin, colMax, rowMax, x0, y0, 3); + + float f[4], g[4]; + + for (int row = 1; row < CACHESIZE - 1; row++) + for (int col = 1 + (FC(y0 - TILEBORDER + row, x0 - TILEBORDER + 1) & 1), indx = row * CACHESIZE + col, c = FC(y0 - TILEBORDER + row, x0 - TILEBORDER + col), d = c / 2; col < CACHESIZE - 1; col += 2, indx += 2) { + assert(indx >= 0 && indx < u * u && c >= 0 && c < 4); + chroma[indx][d] = image[indx][c] - image[indx][1]; + } + + for (int row = rowMin; row < rowMax; row++) + for (int col = colMin + (FC(y0 - TILEBORDER + row, x0 - TILEBORDER + colMin) & 1), indx = row * CACHESIZE + col, c = 1 - FC(y0 - TILEBORDER + row, x0 - TILEBORDER + col) / 2; col < colMax; col += 2, indx += 2) { + f[0] = 1.f / (float)(1.f + fabs(chroma[indx - u - 1][c] - chroma[indx + u + 1][c]) + fabs(chroma[indx - u - 1][c] - chroma[indx - w - 3][c]) + fabs(chroma[indx + u + 1][c] - chroma[indx - w - 3][c])); + f[1] = 1.f / (float)(1.f + fabs(chroma[indx - u + 1][c] - chroma[indx + u - 1][c]) + fabs(chroma[indx - u + 1][c] - chroma[indx - w + 3][c]) + fabs(chroma[indx + u - 1][c] - chroma[indx - w + 3][c])); + f[2] = 1.f / (float)(1.f + fabs(chroma[indx + u - 1][c] - chroma[indx - u + 1][c]) + fabs(chroma[indx + u - 1][c] - chroma[indx + w + 3][c]) + fabs(chroma[indx - u + 1][c] - chroma[indx + w - 3][c])); + f[3] = 1.f / (float)(1.f + fabs(chroma[indx + u + 1][c] - chroma[indx - u - 1][c]) + fabs(chroma[indx + u + 1][c] - chroma[indx + w - 3][c]) + fabs(chroma[indx - u - 1][c] - chroma[indx + w + 3][c])); + g[0] = 1.325f * chroma[indx - u - 1][c] - 0.175f * chroma[indx - w - 3][c] - 0.075f * (chroma[indx - w - 1][c] + chroma[indx - u - 3][c]); + g[1] = 1.325f * chroma[indx - u + 1][c] - 0.175f * chroma[indx - w + 3][c] - 0.075f * (chroma[indx - w + 1][c] + chroma[indx - u + 3][c]); + g[2] = 1.325f * chroma[indx + u - 1][c] - 0.175f * chroma[indx + w - 3][c] - 0.075f * (chroma[indx + w - 1][c] + chroma[indx + u - 3][c]); + g[3] = 1.325f * chroma[indx + u + 1][c] - 0.175f * chroma[indx + w + 3][c] - 0.075f * (chroma[indx + w + 1][c] + chroma[indx + u + 3][c]); + +// g[0] = 1.325f * chroma[indx - u - 1][c] - 0.175f * chroma[indx - w - 3][c] - 0.075f * chroma[indx - w - 1][c] - 0.075f * chroma[indx - u - 3][c]; +// g[1] = 1.325f * chroma[indx - u + 1][c] - 0.175f * chroma[indx - w + 3][c] - 0.075f * chroma[indx - w + 1][c] - 0.075f * chroma[indx - u + 3][c]; +// g[2] = 1.325f * chroma[indx + u - 1][c] - 0.175f * chroma[indx + w - 3][c] - 0.075f * chroma[indx + w - 1][c] - 0.075f * chroma[indx + u - 3][c]; +// g[3] = 1.325f * chroma[indx + u + 1][c] - 0.175f * chroma[indx + w + 3][c] - 0.075f * chroma[indx + w + 1][c] - 0.075f * chroma[indx + u + 3][c]; + + assert(indx >= 0 && indx < u * u && c >= 0 && c < 2); + chroma[indx][c] = (f[0] * g[0] + f[1] * g[1] + f[2] * g[2] + f[3] * g[3]) / (f[0] + f[1] + f[2] + f[3]); + } + + for (int row = rowMin; row < rowMax; row++) + for (int col = colMin + (FC(y0 - TILEBORDER + row, x0 - TILEBORDER + colMin + 1) & 1), indx = row * CACHESIZE + col, c = FC(y0 - TILEBORDER + row, x0 - TILEBORDER + col + 1) / 2; col < colMax; col += 2, indx += 2) + for(int d = 0; d <= 1; c = 1 - c, d++) { + f[0] = 1.f / (1.f + fabs(chroma[indx - u][c] - chroma[indx + u][c]) + fabs(chroma[indx - u][c] - chroma[indx - w][c]) + fabs(chroma[indx + u][c] - chroma[indx - w][c])); + f[1] = 1.f / (1.f + fabs(chroma[indx + 1][c] - chroma[indx - 1][c]) + fabs(chroma[indx + 1][c] - chroma[indx + 3][c]) + fabs(chroma[indx - 1][c] - chroma[indx + 3][c])); + f[2] = 1.f / (1.f + fabs(chroma[indx - 1][c] - chroma[indx + 1][c]) + fabs(chroma[indx - 1][c] - chroma[indx - 3][c]) + fabs(chroma[indx + 1][c] - chroma[indx - 3][c])); + f[3] = 1.f / (1.f + fabs(chroma[indx + u][c] - chroma[indx - u][c]) + fabs(chroma[indx + u][c] - chroma[indx + w][c]) + fabs(chroma[indx - u][c] - chroma[indx + w][c])); + + g[0] = intp(0.875f, chroma[indx - u][c], chroma[indx - w][c]); + g[1] = intp(0.875f, chroma[indx + 1][c], chroma[indx + 3][c]); + g[2] = intp(0.875f, chroma[indx - 1][c], chroma[indx - 3][c]); + g[3] = intp(0.875f, chroma[indx + u][c], chroma[indx + w][c]); + +// g[0] = 0.875f * chroma[indx - u][c] + 0.125f * chroma[indx - w][c]; +// g[1] = 0.875f * chroma[indx + 1][c] + 0.125f * chroma[indx + 3][c]; +// g[2] = 0.875f * chroma[indx - 1][c] + 0.125f * chroma[indx - 3][c]; +// g[3] = 0.875f * chroma[indx + u][c] + 0.125f * chroma[indx + w][c]; + + assert(indx >= 0 && indx < u * u && c >= 0 && c < 2); + chroma[indx][c] = (f[0] * g[0] + f[1] * g[1] + f[2] * g[2] + f[3] * g[3]) / (f[0] + f[1] + f[2] + f[3]); + } + + for(int row = rowMin; row < rowMax; row++) + for(int col = colMin, indx = row * CACHESIZE + col; col < colMax; col++, indx++) { + assert(indx >= 0 && indx < u * u); + + image[indx][0] = chroma[indx][0] + image[indx][1]; + image[indx][2] = chroma[indx][1] + image[indx][1]; + } +} + +// DCB demosaicing main routine +void RawImageSource::dcb_demosaic(int iterations, bool dcb_enhance) +{ +BENCHFUN + double currentProgress = 0.0; + + if(plistener) { + plistener->setProgressStr (Glib::ustring::compose(M("TP_RAW_DMETHOD_PROGRESSBAR"), RAWParams::BayerSensor::getMethodString(RAWParams::BayerSensor::Method::DCB))); + plistener->setProgress (currentProgress); + } + + int wTiles = W / TILESIZE + (W % TILESIZE ? 1 : 0); + int hTiles = H / TILESIZE + (H % TILESIZE ? 1 : 0); + int numTiles = wTiles * hTiles; + int tilesDone = 0; + constexpr int cldf = 2; // factor to multiply cache line distance. 1 = 64 bytes, 2 = 128 bytes ... + +#ifdef _OPENMP + #pragma omp parallel +#endif +{ + // assign working space + char *buffer0 = (char *) malloc(5 * sizeof(float) * CACHESIZE * CACHESIZE + sizeof(uint8_t) * CACHESIZE * CACHESIZE + 3 * cldf * 64 + 63); + // aligned to 64 byte boundary + char *data = (char*)( ( uintptr_t(buffer0) + uintptr_t(63)) / 64 * 64); + + float (*tile)[3] = (float(*)[3]) data; + float (*buffer)[2] = (float(*)[2]) ((char*)tile + sizeof(float) * CACHESIZE * CACHESIZE * 3 + cldf * 64); + float (*chrm)[2] = (float(*)[2]) (buffer); // No overlap in usage of buffer and chrm means we can reuse buffer + uint8_t *map = (uint8_t*) ((char*)buffer + sizeof(float) * CACHESIZE * CACHESIZE * 2 + cldf * 64); + +#ifdef _OPENMP + #pragma omp for schedule(dynamic) nowait +#endif + + for( int iTile = 0; iTile < numTiles; iTile++) { + int xTile = iTile % wTiles; + int yTile = iTile / wTiles; + int x0 = xTile * TILESIZE; + int y0 = yTile * TILESIZE; + + memset(tile, 0, CACHESIZE * CACHESIZE * sizeof * tile); + memset(map, 0, CACHESIZE * CACHESIZE * sizeof * map); + + fill_raw( tile, x0, y0, rawData ); + + if( !xTile || !yTile || xTile == wTiles - 1 || yTile == hTiles - 1) { + fill_border(tile, 6, x0, y0); + } + + copy_to_buffer(buffer, tile); + dcb_hid(tile, x0, y0); + + for (int i = iterations; i > 0; i--) { + dcb_hid2(tile, x0, y0); + dcb_hid2(tile, x0, y0); + dcb_hid2(tile, x0, y0); + dcb_map(tile, map, x0, y0); + dcb_correction(tile, map, x0, y0); + } + + dcb_color(tile, x0, y0); + dcb_pp(tile, x0, y0); + dcb_map(tile, map, x0, y0); + dcb_correction2(tile, map, x0, y0); + dcb_map(tile, map, x0, y0); + dcb_correction(tile, map, x0, y0); + dcb_color(tile, x0, y0); + dcb_map(tile, map, x0, y0); + dcb_correction(tile, map, x0, y0); + dcb_map(tile, map, x0, y0); + dcb_correction(tile, map, x0, y0); + dcb_map(tile, map, x0, y0); + restore_from_buffer(tile, buffer); + + if (!dcb_enhance) + dcb_color(tile, x0, y0); + else + { + memset(chrm, 0, CACHESIZE * CACHESIZE * sizeof * chrm); + dcb_refinement(tile, map, x0, y0); + dcb_color_full(tile, x0, y0, chrm); + } + + /* + dcb_hid(tile, buffer, buffer2, x0, y0); + dcb_color(tile, x0, y0); + + copy_to_buffer(buffer, tile); + + for (int i = iterations; i > 0; i--) { + dcb_hid2(tile, x0, y0); + dcb_hid2(tile, x0, y0); + dcb_hid2(tile, x0, y0); + dcb_map(tile, x0, y0); + dcb_correction(tile, x0, y0); + } + + dcb_color(tile, x0, y0); + dcb_pp(tile, x0, y0); + dcb_map(tile, x0, y0); + dcb_correction2(tile, x0, y0); + dcb_map(tile, x0, y0); + dcb_correction(tile, x0, y0); + dcb_color(tile, x0, y0); + dcb_map(tile, x0, y0); + dcb_correction(tile, x0, y0); + dcb_map(tile, x0, y0); + dcb_correction(tile, x0, y0); + dcb_map(tile, x0, y0); + restore_from_buffer(tile, buffer); + dcb_color_full(tile, x0, y0, chrm); + + if (dcb_enhance) { + dcb_refinement(tile, x0, y0); + dcb_color_full(tile, x0, y0, chrm); + } +*/ + for(int y = 0; y < TILESIZE && y0 + y < H; y++) { + for (int j = 0; j < TILESIZE && x0 + j < W; j++) { + red[y0 + y][x0 + j] = tile[(y + TILEBORDER) * CACHESIZE + TILEBORDER + j][0]; + green[y0 + y][x0 + j] = tile[(y + TILEBORDER) * CACHESIZE + TILEBORDER + j][1]; + blue[y0 + y][x0 + j] = tile[(y + TILEBORDER) * CACHESIZE + TILEBORDER + j][2]; + } + } + +#ifdef _OPENMP + + if(omp_get_thread_num() == 0) +#endif + { + if( plistener && double(tilesDone) / numTiles > currentProgress) { + currentProgress += 0.1; // Show progress each 10% + plistener->setProgress (currentProgress); + } + } + +#ifdef _OPENMP + #pragma omp atomic +#endif + tilesDone++; + } + free(buffer0); +} + + if(plistener) { + plistener->setProgress (1.0); + } +} + +#undef TILEBORDER +#undef TILESIZE +#undef CACHESIZE +} /* namespace */ diff --git a/rtengine/pixelshift.cc b/rtengine/pixelshift.cc index 488538e8a..248336407 100644 --- a/rtengine/pixelshift.cc +++ b/rtengine/pixelshift.cc @@ -323,19 +323,22 @@ BENCHFUN if(motionDetection) { if(!showOnlyMask) { if(bayerParams.pixelShiftMedian) { // We need the demosaiced frames for motion correction - if(bayerParams.pixelShiftLmmse) { + if (bayerParams.pixelShiftDemosaicMethod == bayerParams.getPSDemosaicMethodString(bayerParams.PSDemosaicMethod::LMMSE)) { lmmse_interpolate_omp(winw, winh, *(rawDataFrames[0]), red, green, blue, bayerParams.lmmse_iterations); + } else if (bayerParams.pixelShiftDemosaicMethod == bayerParams.getPSDemosaicMethodString(bayerParams.PSDemosaicMethod::AMAZEVNG4)) { + amaze_vng4_demosaic_RT (winw, winh, *(rawDataFrames[0]), red, green, blue, bayerParams.dualDemosaicContrast); } else { amaze_demosaic_RT(winx, winy, winw, winh, *(rawDataFrames[0]), red, green, blue); } - multi_array2D redTmp(winw, winh); multi_array2D greenTmp(winw, winh); multi_array2D blueTmp(winw, winh); for(int i = 0; i < 3; i++) { - if(bayerParams.pixelShiftLmmse) { + if (bayerParams.pixelShiftDemosaicMethod == bayerParams.getPSDemosaicMethodString(bayerParams.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(bayerParams.PSDemosaicMethod::AMAZEVNG4)) { + amaze_vng4_demosaic_RT (winw, winh, *(rawDataFrames[i + 1]), redTmp[i], greenTmp[i], blueTmp[i], bayerParams.dualDemosaicContrast); } else { amaze_demosaic_RT(winx, winy, winw, winh, *(rawDataFrames[i + 1]), redTmp[i], greenTmp[i], blueTmp[i]); } @@ -359,8 +362,10 @@ BENCHFUN } } } else { - if(bayerParams.pixelShiftLmmse) { + if (bayerParams.pixelShiftDemosaicMethod == bayerParams.getPSDemosaicMethodString(bayerParams.PSDemosaicMethod::LMMSE)) { lmmse_interpolate_omp(winw, winh, rawData, red, green, blue, bayerParams.lmmse_iterations); + } else if (bayerParams.pixelShiftDemosaicMethod == bayerParams.getPSDemosaicMethodString(bayerParams.PSDemosaicMethod::AMAZEVNG4)) { + amaze_vng4_demosaic_RT (winw, winh, rawData, red, green, blue, bayerParams.dualDemosaicContrast); } else { amaze_demosaic_RT(winx, winy, winw, winh, rawData, red, green, blue); } diff --git a/rtengine/procparams.cc b/rtengine/procparams.cc index 3a244f5e8..7fc004aa0 100644 --- a/rtengine/procparams.cc +++ b/rtengine/procparams.cc @@ -2367,10 +2367,10 @@ RAWParams::BayerSensor::BayerSensor() : pixelShiftGreen(true), pixelShiftBlur(true), pixelShiftSmoothFactor(0.7), - pixelShiftLmmse(false), pixelShiftEqualBright(false), pixelShiftEqualBrightChannel(false), pixelShiftNonGreenCross(true), + pixelShiftDemosaicMethod(getPSDemosaicMethodString(PSDemosaicMethod::AMAZE)), dcb_enhance(true), pdafLinesFilter(false) { @@ -2403,10 +2403,10 @@ bool RAWParams::BayerSensor::operator ==(const BayerSensor& other) const && pixelShiftGreen == other.pixelShiftGreen && pixelShiftBlur == other.pixelShiftBlur && pixelShiftSmoothFactor == other.pixelShiftSmoothFactor - && pixelShiftLmmse == other.pixelShiftLmmse && pixelShiftEqualBright == other.pixelShiftEqualBright && pixelShiftEqualBrightChannel == other.pixelShiftEqualBrightChannel && pixelShiftNonGreenCross == other.pixelShiftNonGreenCross + && pixelShiftDemosaicMethod == other.pixelShiftDemosaicMethod && dcb_enhance == other.dcb_enhance && pdafLinesFilter == other.pdafLinesFilter; } @@ -2426,10 +2426,10 @@ void RAWParams::BayerSensor::setPixelShiftDefaults() pixelShiftGreen = true; pixelShiftBlur = true; pixelShiftSmoothFactor = 0.7; - pixelShiftLmmse = false; pixelShiftEqualBright = false; pixelShiftEqualBrightChannel = false; pixelShiftNonGreenCross = true; + pixelShiftDemosaicMethod = getPSDemosaicMethodString(PSDemosaicMethod::AMAZE); } const std::vector& RAWParams::BayerSensor::getMethodStrings() @@ -2458,6 +2458,23 @@ Glib::ustring RAWParams::BayerSensor::getMethodString(Method method) return getMethodStrings()[toUnderlying(method)]; } +const std::vector& RAWParams::BayerSensor::getPSDemosaicMethodStrings() +{ + static const std::vector method_strings { + "amaze", + "amazevng4", + "lmmse" + }; + return method_strings; +} + +Glib::ustring RAWParams::BayerSensor::getPSDemosaicMethodString(PSDemosaicMethod method) +{ + return getPSDemosaicMethodStrings()[toUnderlying(method)]; +} + + + RAWParams::XTransSensor::XTransSensor() : method(getMethodString(Method::THREE_PASS)), ccSteps(0), @@ -3345,10 +3362,10 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo saveToKeyfile(!pedited || pedited->raw.bayersensor.pixelShiftGreen, "RAW Bayer", "pixelShiftGreen", raw.bayersensor.pixelShiftGreen, keyFile); saveToKeyfile(!pedited || pedited->raw.bayersensor.pixelShiftBlur, "RAW Bayer", "pixelShiftBlur", raw.bayersensor.pixelShiftBlur, keyFile); saveToKeyfile(!pedited || pedited->raw.bayersensor.pixelShiftSmooth, "RAW Bayer", "pixelShiftSmoothFactor", raw.bayersensor.pixelShiftSmoothFactor, keyFile); - saveToKeyfile(!pedited || pedited->raw.bayersensor.pixelShiftLmmse, "RAW Bayer", "pixelShiftLmmse", raw.bayersensor.pixelShiftLmmse, keyFile); saveToKeyfile(!pedited || pedited->raw.bayersensor.pixelShiftEqualBright, "RAW Bayer", "pixelShiftEqualBright", raw.bayersensor.pixelShiftEqualBright, keyFile); saveToKeyfile(!pedited || pedited->raw.bayersensor.pixelShiftEqualBrightChannel, "RAW Bayer", "pixelShiftEqualBrightChannel", raw.bayersensor.pixelShiftEqualBrightChannel, keyFile); saveToKeyfile(!pedited || pedited->raw.bayersensor.pixelShiftNonGreenCross, "RAW Bayer", "pixelShiftNonGreenCross", raw.bayersensor.pixelShiftNonGreenCross, keyFile); + saveToKeyfile(!pedited || pedited->raw.bayersensor.pixelShiftDemosaicMethod, "RAW Bayer", "pixelShiftDemosaicMethod", raw.bayersensor.pixelShiftDemosaicMethod, keyFile); saveToKeyfile(!pedited || pedited->raw.bayersensor.pdafLinesFilter, "RAW Bayer", "PDAFLinesFilter", raw.bayersensor.pdafLinesFilter, keyFile); saveToKeyfile(!pedited || pedited->raw.xtranssensor.method, "RAW X-Trans", "Method", raw.xtranssensor.method, keyFile); saveToKeyfile(!pedited || pedited->raw.xtranssensor.ccSteps, "RAW X-Trans", "CcSteps", raw.xtranssensor.ccSteps, keyFile); @@ -4682,10 +4699,26 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited) assignFromKeyfile(keyFile, "RAW Bayer", "pixelShiftGreen", pedited, raw.bayersensor.pixelShiftGreen, pedited->raw.bayersensor.pixelShiftGreen); assignFromKeyfile(keyFile, "RAW Bayer", "pixelShiftBlur", pedited, raw.bayersensor.pixelShiftBlur, pedited->raw.bayersensor.pixelShiftBlur); assignFromKeyfile(keyFile, "RAW Bayer", "pixelShiftSmoothFactor", pedited, raw.bayersensor.pixelShiftSmoothFactor, pedited->raw.bayersensor.pixelShiftSmooth); - assignFromKeyfile(keyFile, "RAW Bayer", "pixelShiftLmmse", pedited, raw.bayersensor.pixelShiftLmmse, pedited->raw.bayersensor.pixelShiftLmmse); assignFromKeyfile(keyFile, "RAW Bayer", "pixelShiftEqualBright", pedited, raw.bayersensor.pixelShiftEqualBright, pedited->raw.bayersensor.pixelShiftEqualBright); assignFromKeyfile(keyFile, "RAW Bayer", "pixelShiftEqualBrightChannel", pedited, raw.bayersensor.pixelShiftEqualBrightChannel, pedited->raw.bayersensor.pixelShiftEqualBrightChannel); assignFromKeyfile(keyFile, "RAW Bayer", "pixelShiftNonGreenCross", pedited, raw.bayersensor.pixelShiftNonGreenCross, pedited->raw.bayersensor.pixelShiftNonGreenCross); + + if (ppVersion < 336) { + if (keyFile.has_key("RAW Bayer", "pixelShiftLmmse")) { + bool useLmmse = keyFile.get_boolean ("RAW Bayer", "pixelShiftLmmse"); + if (useLmmse) { + raw.bayersensor.pixelShiftDemosaicMethod = raw.bayersensor.getPSDemosaicMethodString(raw.bayersensor.PSDemosaicMethod::LMMSE); + } else { + raw.bayersensor.pixelShiftDemosaicMethod = raw.bayersensor.getPSDemosaicMethodString(raw.bayersensor.PSDemosaicMethod::AMAZE); + } + if (pedited) { + pedited->raw.bayersensor.pixelShiftDemosaicMethod = true; + } + } + } else { + assignFromKeyfile(keyFile, "RAW Bayer", "pixelShiftDemosaicMethod", pedited, raw.bayersensor.pixelShiftDemosaicMethod, pedited->raw.bayersensor.pixelShiftDemosaicMethod); + } + assignFromKeyfile(keyFile, "RAW Bayer", "PDAFLinesFilter", pedited, raw.bayersensor.pdafLinesFilter, pedited->raw.bayersensor.pdafLinesFilter); } diff --git a/rtengine/procparams.h b/rtengine/procparams.h index be7784e1b..9b52cc828 100644 --- a/rtengine/procparams.h +++ b/rtengine/procparams.h @@ -1245,6 +1245,12 @@ struct RAWParams { CUSTOM }; + enum class PSDemosaicMethod { + AMAZE, + AMAZEVNG4, + LMMSE + }; + Glib::ustring method; int imageNum; int ccSteps; @@ -1275,10 +1281,10 @@ struct RAWParams { bool pixelShiftGreen; bool pixelShiftBlur; double pixelShiftSmoothFactor; - bool pixelShiftLmmse; bool pixelShiftEqualBright; bool pixelShiftEqualBrightChannel; bool pixelShiftNonGreenCross; + Glib::ustring pixelShiftDemosaicMethod; bool dcb_enhance; bool pdafLinesFilter; @@ -1291,6 +1297,9 @@ struct RAWParams { static const std::vector& getMethodStrings(); static Glib::ustring getMethodString(Method method); + + static const std::vector& getPSDemosaicMethodStrings(); + static Glib::ustring getPSDemosaicMethodString(PSDemosaicMethod method); }; /** diff --git a/rtengine/rawimagesource.cc b/rtengine/rawimagesource.cc index ce300bcd7..c5af124e5 100644 --- a/rtengine/rawimagesource.cc +++ b/rtengine/rawimagesource.cc @@ -2068,7 +2068,7 @@ void RawImageSource::demosaic(const RAWParams &raw) if ( raw.bayersensor.method == RAWParams::BayerSensor::getMethodString(RAWParams::BayerSensor::Method::HPHD) ) { hphd_demosaic (); } else if (raw.bayersensor.method == RAWParams::BayerSensor::getMethodString(RAWParams::BayerSensor::Method::VNG4) ) { - vng4_demosaic (); + vng4_demosaic (rawData, red, green, blue); } else if (raw.bayersensor.method == RAWParams::BayerSensor::getMethodString(RAWParams::BayerSensor::Method::AHD) ) { ahd_demosaic (); } else if (raw.bayersensor.method == RAWParams::BayerSensor::getMethodString(RAWParams::BayerSensor::Method::AMAZE) ) { diff --git a/rtengine/rawimagesource.h b/rtengine/rawimagesource.h index e2467dba6..878886fed 100644 --- a/rtengine/rawimagesource.h +++ b/rtengine/rawimagesource.h @@ -262,13 +262,13 @@ protected: void nodemosaic(bool bw); void eahd_demosaic(); void hphd_demosaic(); - void vng4_demosaic(); + 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); void lmmse_interpolate_omp(int winw, int winh, array2D &rawData, array2D &red, array2D &green, array2D &blue, int iterations); - void amaze_demosaic_RT(int winx, int winy, int winw, int winh, array2D &rawData, array2D &red, array2D &green, array2D &blue);//Emil's code for AMaZE - void amaze_vng4_demosaic_RT(int winw, int winh, array2D &rawData, array2D &red, array2D &green, array2D &blue, double contrast = 0.0); + void amaze_demosaic_RT(int winx, int winy, int winw, int winh, const array2D &rawData, array2D &red, array2D &green, array2D &blue);//Emil's code for AMaZE + void amaze_vng4_demosaic_RT(int winw, int winh, const array2D &rawData, array2D &red, array2D &green, array2D &blue, double contrast = 0.0); void fast_demosaic();//Emil's code for fast demosaicing void dcb_demosaic(int iterations, bool dcb_enhance); void ahd_demosaic(); diff --git a/rtengine/simpleprocess.cc b/rtengine/simpleprocess.cc index 7818871a7..ad622c6bd 100644 --- a/rtengine/simpleprocess.cc +++ b/rtengine/simpleprocess.cc @@ -1465,8 +1465,6 @@ private: } if (params.raw.bayersensor.method == procparams::RAWParams::BayerSensor::getMethodString(procparams::RAWParams::BayerSensor::Method::PIXELSHIFT)) { - params.raw.bayersensor.method = procparams::RAWParams::BayerSensor::getMethodString(params.raw.bayersensor.pixelShiftLmmse ? procparams::RAWParams::BayerSensor::Method::LMMSE : procparams::RAWParams::BayerSensor::Method::AMAZE); - } else if (params.raw.bayersensor.method == procparams::RAWParams::BayerSensor::getMethodString(procparams::RAWParams::BayerSensor::Method::AMAZE)) { params.raw.bayersensor.method = procparams::RAWParams::BayerSensor::getMethodString(procparams::RAWParams::BayerSensor::Method::RCD); } diff --git a/rtgui/bayerprocess.cc b/rtgui/bayerprocess.cc index 339666aa0..23e848fc6 100644 --- a/rtgui/bayerprocess.cc +++ b/rtgui/bayerprocess.cc @@ -29,6 +29,7 @@ BayerProcess::BayerProcess () : FoldableToolPanel(this, "bayerprocess", M("TP_RA auto m = ProcEventMapper::getInstance(); EvDemosaicContrast = m->newEvent(DEMOSAIC, "HISTORY_MSG_DUALDEMOSAIC_CONTRAST"); + EvDemosaicPixelshiftDemosaicMethod = m->newEvent(DEMOSAIC, "HISTORY_MSG_PIXELSHIFT_DEMOSAIC"); Gtk::HBox* hb1 = Gtk::manage (new Gtk::HBox ()); hb1->pack_start (*Gtk::manage (new Gtk::Label ( M("TP_RAW_DMETHOD") + ": ")), Gtk::PACK_SHRINK, 4); @@ -149,6 +150,17 @@ BayerProcess::BayerProcess () : FoldableToolPanel(this, "bayerprocess", M("TP_RA pixelShiftShowMotionMaskOnly->set_tooltip_text (M("TP_RAW_PIXELSHIFTSHOWMOTIONMASKONLY_TOOLTIP")); pixelShiftFrame->pack_start(*pixelShiftShowMotionMaskOnly); + + Gtk::HBox* hb4 = Gtk::manage (new Gtk::HBox ()); + hb4->pack_start (*Gtk::manage (new Gtk::Label ( M("TP_RAW_PIXELSHIFTDMETHOD") + ": ")), Gtk::PACK_SHRINK, 4); + pixelShiftDemosaicMethod = Gtk::manage (new MyComboBoxText ()); + for(const auto method_string : procparams::RAWParams::BayerSensor::getPSDemosaicMethodStrings()) { + pixelShiftDemosaicMethod->append(M("TP_RAW_" + Glib::ustring(method_string).uppercase())); + } + pixelShiftDemosaicMethod->set_active(0); + hb4->pack_start(*pixelShiftDemosaicMethod); + pixelShiftOptions->pack_start(*hb4); + pixelShiftGreen = Gtk::manage (new CheckBox(M("TP_RAW_PIXELSHIFTGREEN"), multiImage)); pixelShiftGreen->setCheckBoxListener (this); pixelShiftOptions->pack_start(*pixelShiftGreen); @@ -207,13 +219,6 @@ BayerProcess::BayerProcess () : FoldableToolPanel(this, "bayerprocess", M("TP_RA pixelShiftMedian->set_tooltip_text (M("TP_RAW_PIXELSHIFTMEDIAN_TOOLTIP")); pixelShiftOptions->pack_start(*pixelShiftMedian); - - pixelShiftLmmse = Gtk::manage (new CheckBox(M("TP_RAW_PIXELSHIFTLMMSE"), multiImage)); - pixelShiftLmmse->setCheckBoxListener (this); - pixelShiftLmmse->set_tooltip_text (M("TP_RAW_PIXELSHIFTLMMSE_TOOLTIP")); - pixelShiftOptions->pack_start(*pixelShiftLmmse); - - pixelShiftFrame->pack_start(*pixelShiftOptions); pixelShiftOptions->hide(); @@ -222,6 +227,7 @@ BayerProcess::BayerProcess () : FoldableToolPanel(this, "bayerprocess", M("TP_RA method->connect(method->signal_changed().connect( sigc::mem_fun(*this, &BayerProcess::methodChanged) )); imageNumber->connect(imageNumber->signal_changed().connect( sigc::mem_fun(*this, &BayerProcess::imageNumberChanged) )); pixelShiftMotionMethod->connect(pixelShiftMotionMethod->signal_changed().connect( sigc::mem_fun(*this, &BayerProcess::pixelShiftMotionMethodChanged) )); + pixelShiftDemosaicMethod->connect(pixelShiftDemosaicMethod->signal_changed().connect( sigc::mem_fun(*this, &BayerProcess::pixelShiftDemosaicMethodChanged) )); } @@ -230,6 +236,7 @@ void BayerProcess::read(const rtengine::procparams::ProcParams* pp, const Params disableListener (); method->block (true); imageNumber->block (true); + pixelShiftDemosaicMethod->block(true); //allEnhconn.block (true); method->set_active(std::numeric_limits::max()); @@ -242,8 +249,14 @@ void BayerProcess::read(const rtengine::procparams::ProcParams* pp, const Params break; } } + pixelShiftDemosaicMethod->set_active(std::numeric_limits::max()); + for (size_t i = 0; i < procparams::RAWParams::BayerSensor::getPSDemosaicMethodStrings().size(); ++i) { + if (pp->raw.bayersensor.pixelShiftDemosaicMethod == procparams::RAWParams::BayerSensor::getPSDemosaicMethodStrings()[i]) { + pixelShiftDemosaicMethod->set_active(i); + break; + } + } - //allEnhance->set_active(pp->raw.bayersensor.all_enhance); dcbIterations->setValue (pp->raw.bayersensor.dcb_iterations); dcbEnhance->setValue (pp->raw.bayersensor.dcb_enhance); @@ -260,7 +273,6 @@ void BayerProcess::read(const rtengine::procparams::ProcParams* pp, const Params pixelShiftSmooth->set_sensitive (pp->raw.bayersensor.pixelShiftBlur); } pixelShiftSmooth->setValue (pp->raw.bayersensor.pixelShiftSmoothFactor); - pixelShiftLmmse->setValue (pp->raw.bayersensor.pixelShiftLmmse); pixelShiftEqualBright->setValue (pp->raw.bayersensor.pixelShiftEqualBright); pixelShiftEqualBrightChannel->set_sensitive (pp->raw.bayersensor.pixelShiftEqualBright); pixelShiftEqualBrightChannel->setValue (pp->raw.bayersensor.pixelShiftEqualBrightChannel); @@ -286,7 +298,6 @@ void BayerProcess::read(const rtengine::procparams::ProcParams* pp, const Params pixelShiftGreen->setEdited (pedited->raw.bayersensor.pixelShiftGreen); pixelShiftBlur->setEdited (pedited->raw.bayersensor.pixelShiftBlur); pixelShiftSmooth->setEditedState ( pedited->raw.bayersensor.pixelShiftSmooth ? Edited : UnEdited); - pixelShiftLmmse->setEdited (pedited->raw.bayersensor.pixelShiftLmmse); pixelShiftEqualBright->setEdited (pedited->raw.bayersensor.pixelShiftEqualBright); pixelShiftEqualBrightChannel->setEdited (pedited->raw.bayersensor.pixelShiftEqualBrightChannel); pixelShiftNonGreenCross->setEdited (pedited->raw.bayersensor.pixelShiftNonGreenCross); @@ -298,12 +309,19 @@ void BayerProcess::read(const rtengine::procparams::ProcParams* pp, const Params if(!pedited->raw.bayersensor.method) { method->set_active(std::numeric_limits::max()); // No name } + if(!pedited->raw.bayersensor.imageNum) { imageNumber->set_active_text(M("GENERAL_UNCHANGED")); } + if(!pedited->raw.bayersensor.pixelShiftMotionCorrectionMethod) { pixelShiftMotionMethod->set_active_text(M("GENERAL_UNCHANGED")); } + + if(!pedited->raw.bayersensor.pixelShiftDemosaicMethod) { + pixelShiftDemosaicMethod->set_active(std::numeric_limits::max()); // No name + } + } if (!batchMode) { @@ -330,6 +348,7 @@ void BayerProcess::read(const rtengine::procparams::ProcParams* pp, const Params method->block (false); imageNumber->block (false); + pixelShiftDemosaicMethod->block(false); //allEnhconn.block (false); enableListener (); @@ -353,7 +372,6 @@ void BayerProcess::write( rtengine::procparams::ProcParams* pp, ParamsEdited* pe pp->raw.bayersensor.pixelShiftGreen = pixelShiftGreen->getLastActive (); pp->raw.bayersensor.pixelShiftBlur = pixelShiftBlur->getLastActive (); pp->raw.bayersensor.pixelShiftSmoothFactor = pixelShiftSmooth->getValue(); - pp->raw.bayersensor.pixelShiftLmmse = pixelShiftLmmse->getLastActive (); pp->raw.bayersensor.pixelShiftEqualBright = pixelShiftEqualBright->getLastActive (); pp->raw.bayersensor.pixelShiftEqualBrightChannel = pixelShiftEqualBrightChannel->getLastActive (); pp->raw.bayersensor.pixelShiftNonGreenCross = pixelShiftNonGreenCross->getLastActive (); @@ -368,6 +386,11 @@ void BayerProcess::write( rtengine::procparams::ProcParams* pp, ParamsEdited* pe pp->raw.bayersensor.imageNum = currentRow; } + currentRow = pixelShiftDemosaicMethod->get_active_row_number(); + if( currentRow >= 0 && currentRow < std::numeric_limits::max()) { + pp->raw.bayersensor.pixelShiftDemosaicMethod = procparams::RAWParams::BayerSensor::getPSDemosaicMethodString(RAWParams::BayerSensor::PSDemosaicMethod(currentRow)); + } + if (pedited) { pedited->raw.bayersensor.ccSteps = ccSteps->getEditedState (); @@ -379,6 +402,7 @@ void BayerProcess::write( rtengine::procparams::ProcParams* pp, ParamsEdited* pe pedited->raw.bayersensor.lmmseIterations = lmmseIterations->getEditedState (); pedited->raw.bayersensor.dualDemosaicContrast = dualDemosaicContrast->getEditedState (); pedited->raw.bayersensor.pixelShiftMotionCorrectionMethod = pixelShiftMotionMethod->get_active_text() != M("GENERAL_UNCHANGED"); + pedited->raw.bayersensor.pixelShiftDemosaicMethod = pixelShiftDemosaicMethod->get_active_row_number() != std::numeric_limits::max(); pedited->raw.bayersensor.pixelShiftEperIso = pixelShiftEperIso->getEditedState (); pedited->raw.bayersensor.pixelShiftSigma = pixelShiftSigma->getEditedState (); pedited->raw.bayersensor.pixelShiftShowMotion = !pixelShiftShowMotion->get_inconsistent(); @@ -388,7 +412,6 @@ void BayerProcess::write( rtengine::procparams::ProcParams* pp, ParamsEdited* pe pedited->raw.bayersensor.pixelShiftGreen = !pixelShiftGreen->get_inconsistent(); pedited->raw.bayersensor.pixelShiftBlur = !pixelShiftBlur->get_inconsistent(); pedited->raw.bayersensor.pixelShiftSmooth = pixelShiftSmooth->getEditedState(); - pedited->raw.bayersensor.pixelShiftLmmse = !pixelShiftLmmse->get_inconsistent(); pedited->raw.bayersensor.pixelShiftEqualBright = !pixelShiftEqualBright->get_inconsistent(); pedited->raw.bayersensor.pixelShiftEqualBrightChannel = !pixelShiftEqualBrightChannel->get_inconsistent(); pedited->raw.bayersensor.pixelShiftNonGreenCross = !pixelShiftNonGreenCross->get_inconsistent(); @@ -423,6 +446,8 @@ void BayerProcess::setBatchMode(bool batchMode) method->set_active(std::numeric_limits::max()); // No name pixelShiftMotionMethod->append (M("GENERAL_UNCHANGED")); pixelShiftMotionMethod->set_active_text (M("GENERAL_UNCHANGED")); + pixelShiftDemosaicMethod->append (M("GENERAL_UNCHANGED")); + pixelShiftDemosaicMethod->set_active(std::numeric_limits::max()); // No name imageNumber->append (M("GENERAL_UNCHANGED")); imageNumber->set_active_text (M("GENERAL_UNCHANGED")); ToolPanel::setBatchMode (batchMode); @@ -535,6 +560,19 @@ void BayerProcess::methodChanged () } } +void BayerProcess::pixelShiftDemosaicMethodChanged () +{ + + if (listener) { + const int curSelection = pixelShiftDemosaicMethod->get_active_row_number(); + if (curSelection >= 0 && curSelection < std::numeric_limits::max()) { + const RAWParams::BayerSensor::PSDemosaicMethod method = RAWParams::BayerSensor::PSDemosaicMethod(curSelection); + Glib::ustring methodName = procparams::RAWParams::BayerSensor::getPSDemosaicMethodString(method);; + listener->panelChanged (EvDemosaicPixelshiftDemosaicMethod, methodName); + } + } +} + void BayerProcess::imageNumberChanged () { if (listener) { @@ -579,10 +617,6 @@ void BayerProcess::checkBoxToggled (CheckBox* c, CheckValue newval) if (listener) { listener->panelChanged (EvPixelShiftBlur, pixelShiftBlur->getValueAsStr ()); } - } else if (c == pixelShiftLmmse) { - if (listener) { - listener->panelChanged (EvPixelShiftLmmse, pixelShiftLmmse->getValueAsStr ()); - } } else if (c == pixelShiftEqualBright) { if (!batchMode) { pixelShiftEqualBrightChannel->set_sensitive(newval != CheckValue::off); diff --git a/rtgui/bayerprocess.h b/rtgui/bayerprocess.h index ee532f27c..bfcb99878 100644 --- a/rtgui/bayerprocess.h +++ b/rtgui/bayerprocess.h @@ -42,6 +42,7 @@ protected: Gtk::VBox *pixelShiftFrame; Gtk::VBox *pixelShiftOptions; MyComboBoxText* pixelShiftMotionMethod; + MyComboBoxText* pixelShiftDemosaicMethod; CheckBox* pixelShiftShowMotion; CheckBox* pixelShiftShowMotionMaskOnly; CheckBox* pixelShiftNonGreenCross; @@ -49,7 +50,6 @@ protected: CheckBox* pixelShiftBlur; CheckBox* pixelShiftHoleFill; CheckBox* pixelShiftMedian; - CheckBox* pixelShiftLmmse; CheckBox* pixelShiftEqualBright; CheckBox* pixelShiftEqualBrightChannel; Adjuster* pixelShiftSmooth; @@ -61,6 +61,7 @@ protected: IdleRegister idle_register; rtengine::ProcEvent EvDemosaicContrast; + rtengine::ProcEvent EvDemosaicPixelshiftDemosaicMethod; public: BayerProcess (); @@ -77,6 +78,7 @@ public: void adjusterChanged(Adjuster* a, double newval); void checkBoxToggled(CheckBox* c, CheckValue newval); void pixelShiftMotionMethodChanged(); + void pixelShiftDemosaicMethodChanged(); void FrameCountChanged(int n, int frameNum); }; diff --git a/rtgui/paramsedited.cc b/rtgui/paramsedited.cc index bf5a63fa8..9e6d3b6e7 100644 --- a/rtgui/paramsedited.cc +++ b/rtgui/paramsedited.cc @@ -414,10 +414,10 @@ void ParamsEdited::set (bool v) raw.bayersensor.pixelShiftGreen = v; raw.bayersensor.pixelShiftBlur = v; raw.bayersensor.pixelShiftSmooth = v; - raw.bayersensor.pixelShiftLmmse = v; raw.bayersensor.pixelShiftEqualBright = v; raw.bayersensor.pixelShiftEqualBrightChannel = v; raw.bayersensor.pixelShiftNonGreenCross = v; + raw.bayersensor.pixelShiftDemosaicMethod = v; raw.bayersensor.greenEq = v; raw.bayersensor.linenoise = v; raw.bayersensor.linenoiseDirection = v; @@ -964,10 +964,10 @@ void ParamsEdited::initFrom (const std::vector raw.bayersensor.pixelShiftGreen = raw.bayersensor.pixelShiftGreen && p.raw.bayersensor.pixelShiftGreen == other.raw.bayersensor.pixelShiftGreen; raw.bayersensor.pixelShiftBlur = raw.bayersensor.pixelShiftBlur && p.raw.bayersensor.pixelShiftBlur == other.raw.bayersensor.pixelShiftBlur; raw.bayersensor.pixelShiftSmooth = raw.bayersensor.pixelShiftSmooth && p.raw.bayersensor.pixelShiftSmoothFactor == other.raw.bayersensor.pixelShiftSmoothFactor; - raw.bayersensor.pixelShiftLmmse = raw.bayersensor.pixelShiftLmmse && p.raw.bayersensor.pixelShiftLmmse == other.raw.bayersensor.pixelShiftLmmse; raw.bayersensor.pixelShiftEqualBright = raw.bayersensor.pixelShiftEqualBright && p.raw.bayersensor.pixelShiftEqualBright == other.raw.bayersensor.pixelShiftEqualBright; raw.bayersensor.pixelShiftEqualBrightChannel = raw.bayersensor.pixelShiftEqualBrightChannel && p.raw.bayersensor.pixelShiftEqualBrightChannel == other.raw.bayersensor.pixelShiftEqualBrightChannel; raw.bayersensor.pixelShiftNonGreenCross = raw.bayersensor.pixelShiftNonGreenCross && p.raw.bayersensor.pixelShiftNonGreenCross == other.raw.bayersensor.pixelShiftNonGreenCross; + raw.bayersensor.pixelShiftDemosaicMethod = raw.bayersensor.pixelShiftDemosaicMethod && p.raw.bayersensor.pixelShiftDemosaicMethod == other.raw.bayersensor.pixelShiftDemosaicMethod; raw.bayersensor.greenEq = raw.bayersensor.greenEq && p.raw.bayersensor.greenthresh == other.raw.bayersensor.greenthresh; raw.bayersensor.linenoise = raw.bayersensor.linenoise && p.raw.bayersensor.linenoise == other.raw.bayersensor.linenoise; raw.bayersensor.linenoiseDirection = raw.bayersensor.linenoiseDirection && p.raw.bayersensor.linenoiseDirection == other.raw.bayersensor.linenoiseDirection; @@ -2542,10 +2542,6 @@ void ParamsEdited::combine (rtengine::procparams::ProcParams& toEdit, const rten toEdit.raw.bayersensor.pixelShiftSmoothFactor = mods.raw.bayersensor.pixelShiftSmoothFactor; } - if (raw.bayersensor.pixelShiftLmmse) { - toEdit.raw.bayersensor.pixelShiftLmmse = mods.raw.bayersensor.pixelShiftLmmse; - } - if (raw.bayersensor.pixelShiftEqualBright) { toEdit.raw.bayersensor.pixelShiftEqualBright = mods.raw.bayersensor.pixelShiftEqualBright; } @@ -2558,6 +2554,10 @@ void ParamsEdited::combine (rtengine::procparams::ProcParams& toEdit, const rten toEdit.raw.bayersensor.pixelShiftNonGreenCross = mods.raw.bayersensor.pixelShiftNonGreenCross; } + if (raw.bayersensor.pixelShiftDemosaicMethod) { + toEdit.raw.bayersensor.pixelShiftDemosaicMethod = mods.raw.bayersensor.pixelShiftDemosaicMethod; + } + if (raw.bayersensor.greenEq) { toEdit.raw.bayersensor.greenthresh = dontforceSet && options.baBehav[ADDSET_PREPROCESS_GREENEQUIL] ? toEdit.raw.bayersensor.greenthresh + mods.raw.bayersensor.greenthresh : mods.raw.bayersensor.greenthresh; } @@ -3080,7 +3080,7 @@ bool RAWParamsEdited::BayerSensor::isUnchanged() const { return method && imageNum && dcbIterations && dcbEnhance && lmmseIterations && dualDemosaicContrast /*&& allEnhance*/ && greenEq && pixelShiftMotionCorrectionMethod && pixelShiftEperIso && pixelShiftSigma && pixelShiftShowMotion && pixelShiftShowMotionMaskOnly - && pixelShiftHoleFill && pixelShiftMedian && pixelShiftNonGreenCross && pixelShiftGreen && pixelShiftBlur && pixelShiftSmooth && pixelShiftLmmse && pixelShiftEqualBright && pixelShiftEqualBrightChannel + && pixelShiftHoleFill && pixelShiftMedian && pixelShiftNonGreenCross && pixelShiftDemosaicMethod && pixelShiftGreen && pixelShiftBlur && pixelShiftSmooth && pixelShiftEqualBright && pixelShiftEqualBrightChannel && linenoise && linenoiseDirection && pdafLinesFilter && exBlack0 && exBlack1 && exBlack2 && exBlack3 && exTwoGreen; } diff --git a/rtgui/paramsedited.h b/rtgui/paramsedited.h index 5b3370b9a..1db298dfd 100644 --- a/rtgui/paramsedited.h +++ b/rtgui/paramsedited.h @@ -742,10 +742,10 @@ public: bool pixelShiftGreen; bool pixelShiftBlur; bool pixelShiftSmooth; - bool pixelShiftLmmse; bool pixelShiftEqualBright; bool pixelShiftEqualBrightChannel; bool pixelShiftNonGreenCross; + bool pixelShiftDemosaicMethod; //bool allEnhance; bool greenEq; diff --git a/rtgui/partialpastedlg.cc b/rtgui/partialpastedlg.cc index c9ed1cd14..99411e46c 100644 --- a/rtgui/partialpastedlg.cc +++ b/rtgui/partialpastedlg.cc @@ -852,7 +852,7 @@ void PartialPasteDlg::applyPaste (rtengine::procparams::ProcParams* dstPP, Param filterPE.raw.bayersensor.pixelShiftEqualBrightChannel = falsePE.raw.bayersensor.pixelShiftEqualBrightChannel; filterPE.raw.bayersensor.pixelShiftGreen = falsePE.raw.bayersensor.pixelShiftGreen; filterPE.raw.bayersensor.pixelShiftHoleFill = falsePE.raw.bayersensor.pixelShiftHoleFill; - filterPE.raw.bayersensor.pixelShiftLmmse = falsePE.raw.bayersensor.pixelShiftLmmse; + filterPE.raw.bayersensor.pixelShiftDemosaicMethod = falsePE.raw.bayersensor.pixelShiftDemosaicMethod; filterPE.raw.bayersensor.pixelShiftMedian = falsePE.raw.bayersensor.pixelShiftMedian; filterPE.raw.bayersensor.pixelShiftMotionCorrectionMethod = falsePE.raw.bayersensor.pixelShiftMotionCorrectionMethod; filterPE.raw.bayersensor.pixelShiftNonGreenCross = falsePE.raw.bayersensor.pixelShiftNonGreenCross; diff --git a/rtgui/ppversion.h b/rtgui/ppversion.h index 2b6bc49de..1fb34ca0a 100644 --- a/rtgui/ppversion.h +++ b/rtgui/ppversion.h @@ -1,11 +1,13 @@ #pragma once // This number has to be incremented whenever the PP3 file format is modified or the behaviour of a tool changes -#define PPVERSION 335 +#define PPVERSION 336 #define PPVERSION_AEXP 301 //value of PPVERSION when auto exposure algorithm was modified /* Log of version changes + 336 2018-06-01 + new demosaic method combobox for pixelshift 335 2018-05-30 new contrast adjuster in Bayer process tool 334 2018-05-13 From 8f167c945a4a44c64cfef04f696b9c13282777f7 Mon Sep 17 00:00:00 2001 From: heckflosse Date: Fri, 1 Jun 2018 20:48:17 +0200 Subject: [PATCH 10/42] Removed accidently committed file --- rtengine/demosaic_algos.cc.save-failed | 3861 ------------------------ 1 file changed, 3861 deletions(-) delete mode 100644 rtengine/demosaic_algos.cc.save-failed diff --git a/rtengine/demosaic_algos.cc.save-failed b/rtengine/demosaic_algos.cc.save-failed deleted file mode 100644 index 29ee67332..000000000 --- a/rtengine/demosaic_algos.cc.save-failed +++ /dev/null @@ -1,3861 +0,0 @@ -/* - * This file is part of RawTherapee. - * - * Copyright (c) 2004-2010 Gabor Horvath - * - * 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 -#include - -#include "rawimagesource.h" -#include "rawimagesource_i.h" -#include "jaggedarray.h" -#include "rawimage.h" -#include "mytime.h" -#include "iccmatrices.h" -#include "iccstore.h" -#include "image8.h" -#include "curves.h" -#include "dfmanager.h" -#include "slicer.h" -#include "rt_math.h" -#include "color.h" -#include "../rtgui/multilangmgr.h" -#include "procparams.h" -#include "sleef.c" -#include "opthelper.h" -#include "median.h" -#include "StopWatch.h" -#ifdef _OPENMP -#include -#endif - -using namespace std; - -namespace rtengine -{ -#undef ABS -#undef DIST - -#define ABS(a) ((a)<0?-(a):(a)) -#define DIST(a,b) (ABS(a-b)) -#define CLIREF(x) LIM(x,-200000.0f,200000.0f) // avoid overflow : do not act directly on image[] or pix[] -#define x1125(a) (a + xdivf(a, 3)) -#define x0875(a) (a - xdivf(a, 3)) -#define x0250(a) xdivf(a, 2) -#define x00625(a) xdivf(a, 4) -#define x0125(a) xdivf(a, 3) - -extern const Settings* settings; -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -void RawImageSource::eahd_demosaic () -{ - if (plistener) { - plistener->setProgressStr (Glib::ustring::compose(M("TP_RAW_DMETHOD_PROGRESSBAR"), RAWParams::BayerSensor::getMethodString(RAWParams::BayerSensor::Method::EAHD))); - plistener->setProgress (0.0); - } - - // prepare cache and constants for cielab conversion - //TODO: revisit after conversion to D50 illuminant - lc00 = (0.412453 * imatrices.rgb_cam[0][0] + 0.357580 * imatrices.rgb_cam[0][1] + 0.180423 * imatrices.rgb_cam[0][2]) ;// / 0.950456; - lc01 = (0.412453 * imatrices.rgb_cam[1][0] + 0.357580 * imatrices.rgb_cam[1][1] + 0.180423 * imatrices.rgb_cam[1][2]) ;// / 0.950456; - lc02 = (0.412453 * imatrices.rgb_cam[2][0] + 0.357580 * imatrices.rgb_cam[2][1] + 0.180423 * imatrices.rgb_cam[2][2]) ;// / 0.950456; - - lc10 = 0.212671 * imatrices.rgb_cam[0][0] + 0.715160 * imatrices.rgb_cam[0][1] + 0.072169 * imatrices.rgb_cam[0][2]; - lc11 = 0.212671 * imatrices.rgb_cam[1][0] + 0.715160 * imatrices.rgb_cam[1][1] + 0.072169 * imatrices.rgb_cam[1][2]; - lc12 = 0.212671 * imatrices.rgb_cam[2][0] + 0.715160 * imatrices.rgb_cam[2][1] + 0.072169 * imatrices.rgb_cam[2][2]; - - lc20 = (0.019334 * imatrices.rgb_cam[0][0] + 0.119193 * imatrices.rgb_cam[0][1] + 0.950227 * imatrices.rgb_cam[0][2]) ;// / 1.088754; - lc21 = (0.019334 * imatrices.rgb_cam[1][0] + 0.119193 * imatrices.rgb_cam[1][1] + 0.950227 * imatrices.rgb_cam[1][2]) ;// / 1.088754; - lc22 = (0.019334 * imatrices.rgb_cam[2][0] + 0.119193 * imatrices.rgb_cam[2][1] + 0.950227 * imatrices.rgb_cam[2][2]) ;// / 1.088754; - - int maxindex = 3 * 65536; //2*65536 3 = avoid crash 3/2013 J.Desmis - cache = new double[maxindex]; - threshold = (int)(0.008856 * MAXVALD); - - for (int i = 0; i < maxindex; i++) { - cache[i] = std::cbrt(double(i) / MAXVALD); - } - - // end of cielab preparation - - JaggedArray - rh (W, 3), gh (W, 4), bh (W, 3), - rv (W, 3), gv (W, 4), bv (W, 3), - lLh (W, 3), lah (W, 3), lbh (W, 3), - lLv (W, 3), lav (W, 3), lbv (W, 3), - homh (W, 3), homv (W, 3); - - // interpolate first two lines - interpolate_row_g (gh[0], gv[0], 0); - interpolate_row_g (gh[1], gv[1], 1); - interpolate_row_g (gh[2], gv[2], 2); - interpolate_row_rb (rh[0], bh[0], nullptr, gh[0], gh[1], 0); - interpolate_row_rb (rv[0], bv[0], nullptr, gv[0], gv[1], 0); - interpolate_row_rb (rh[1], bh[1], gh[0], gh[1], gh[2], 1); - interpolate_row_rb (rv[1], bv[1], gv[0], gv[1], gv[2], 1); - - convert_to_cielab_row (rh[0], gh[0], bh[0], lLh[0], lah[0], lbh[0]); - convert_to_cielab_row (rv[0], gv[0], bv[0], lLv[0], lav[0], lbv[0]); - convert_to_cielab_row (rh[1], gh[1], bh[1], lLh[1], lah[1], lbh[1]); - convert_to_cielab_row (rv[1], gv[1], bv[1], lLv[1], lav[1], lbv[1]); - - for (int j = 0; j < W; j++) { - homh[0][j] = 0; - homv[0][j] = 0; - homh[1][j] = 0; - homv[1][j] = 0; - } - - int dLmaph[9]; - int dLmapv[9]; - int dCamaph[9]; - int dCamapv[9]; - int dCbmaph[9]; - int dCbmapv[9]; - - for (int i = 1; i < H - 1; i++) { - int ix = i % 3; - int imx = (i - 1) % 3; - int ipx = (i + 1) % 3; - - if (i < H - 2) { - interpolate_row_g (gh[(i + 2) % 4], gv[(i + 2) % 4], i + 2); - interpolate_row_rb (rh[(i + 1) % 3], bh[(i + 1) % 3], gh[i % 4], gh[(i + 1) % 4], gh[(i + 2) % 4], i + 1); - interpolate_row_rb (rv[(i + 1) % 3], bv[(i + 1) % 3], gv[i % 4], gv[(i + 1) % 4], gv[(i + 2) % 4], i + 1); - } else { - interpolate_row_rb (rh[(i + 1) % 3], bh[(i + 1) % 3], gh[i % 4], gh[(i + 1) % 4], nullptr, i + 1); - interpolate_row_rb (rv[(i + 1) % 3], bv[(i + 1) % 3], gv[i % 4], gv[(i + 1) % 4], nullptr, i + 1); - } - - convert_to_cielab_row (rh[(i + 1) % 3], gh[(i + 1) % 4], bh[(i + 1) % 3], lLh[(i + 1) % 3], lah[(i + 1) % 3], lbh[(i + 1) % 3]); - convert_to_cielab_row (rv[(i + 1) % 3], gv[(i + 1) % 4], bv[(i + 1) % 3], lLv[(i + 1) % 3], lav[(i + 1) % 3], lbv[(i + 1) % 3]); - - for (int j = 0; j < W; j++) { - homh[ipx][j] = 0; - homv[ipx][j] = 0; - } - - int sh, sv, idx; - - for (int j = 1; j < W - 1; j++) { - int dmi = 0; - - for (int x = -1; x <= 1; x++) { - idx = (i + x) % 3; - - for (int y = -1; y <= 1; y++) { - // compute distance in a, b, and L - if (dmi < 4) { - sh = homh[idx][j + y]; - sv = homv[idx][j + y]; - - if (sh > sv) { // fixate horizontal pixel - dLmaph[dmi] = DIST(lLh[ix][j], lLh[idx][j + y]); - dCamaph[dmi] = DIST(lah[ix][j], lah[idx][j + y]); - dCbmaph[dmi] = DIST(lbh[ix][j], lbh[idx][j + y]); - dLmapv[dmi] = DIST(lLv[ix][j], lLh[idx][j + y]); - dCamapv[dmi] = DIST(lav[ix][j], lah[idx][j + y]); - dCbmapv[dmi] = DIST(lbv[ix][j], lbh[idx][j + y]); - } else if (sh < sv) { - dLmaph[dmi] = DIST(lLh[ix][j], lLv[idx][j + y]); - dCamaph[dmi] = DIST(lah[ix][j], lav[idx][j + y]); - dCbmaph[dmi] = DIST(lbh[ix][j], lbv[idx][j + y]); - dLmapv[dmi] = DIST(lLv[ix][j], lLv[idx][j + y]); - dCamapv[dmi] = DIST(lav[ix][j], lav[idx][j + y]); - dCbmapv[dmi] = DIST(lbv[ix][j], lbv[idx][j + y]); - } else { - dLmaph[dmi] = DIST(lLh[ix][j], lLh[idx][j + y]); - dCamaph[dmi] = DIST(lah[ix][j], lah[idx][j + y]); - dCbmaph[dmi] = DIST(lbh[ix][j], lbh[idx][j + y]); - dLmapv[dmi] = DIST(lLv[ix][j], lLv[idx][j + y]); - dCamapv[dmi] = DIST(lav[ix][j], lav[idx][j + y]); - dCbmapv[dmi] = DIST(lbv[ix][j], lbv[idx][j + y]); - } - } else { - dLmaph[dmi] = DIST(lLh[ix][j], lLh[idx][j + y]); - dCamaph[dmi] = DIST(lah[ix][j], lah[idx][j + y]); - dCbmaph[dmi] = DIST(lbh[ix][j], lbh[idx][j + y]); - dLmapv[dmi] = DIST(lLv[ix][j], lLv[idx][j + y]); - dCamapv[dmi] = DIST(lav[ix][j], lav[idx][j + y]); - dCbmapv[dmi] = DIST(lbv[ix][j], lbv[idx][j + y]); - } - - dmi++; - } - } - - // compute eL & eC - int eL = min(max(dLmaph[3], dLmaph[5]), max(dLmapv[1], dLmapv[7])); - int eCa = min(max(dCamaph[3], dCamaph[5]), max(dCamapv[1], dCamapv[7])); - int eCb = min(max(dCbmaph[3], dCbmaph[5]), max(dCbmapv[1], dCbmapv[7])); - - int wh = 0; - - for (int dmi = 0; dmi < 9; dmi++) - if (dLmaph[dmi] <= eL && dCamaph[dmi] <= eCa && dCbmaph[dmi] <= eCb) { - wh++; - } - - int wv = 0; - - for (int dmi = 0; dmi < 9; dmi++) - if (dLmapv[dmi] <= eL && dCamapv[dmi] <= eCa && dCbmapv[dmi] <= eCb) { - wv++; - } - - homh[imx][j - 1] += wh; - homh[imx][j] += wh; - homh[imx][j + 1] += wh; - homh[ix][j - 1] += wh; - homh[ix][j] += wh; - homh[ix][j + 1] += wh; - homh[ipx][j - 1] += wh; - homh[ipx][j] += wh; - homh[ipx][j + 1] += wh; - - homv[imx][j - 1] += wv; - homv[imx][j] += wv; - homv[imx][j + 1] += wv; - homv[ix][j - 1] += wv; - homv[ix][j] += wv; - homv[ix][j + 1] += wv; - homv[ipx][j - 1] += wv; - homv[ipx][j] += wv; - homv[ipx][j + 1] += wv; - } - -//} - // finalize image - int hc, vc; - - for (int j = 0; j < W; j++) { - if (ri->ISGREEN(i - 1, j)) { - green[i - 1][j] = rawData[i - 1][j]; - } else { - hc = homh[imx][j]; - vc = homv[imx][j]; - - if (hc > vc) { - green[i - 1][j] = gh[(i - 1) % 4][j]; - } else if (hc < vc) { - green[i - 1][j] = gv[(i - 1) % 4][j]; - } else { - green[i - 1][j] = (gh[(i - 1) % 4][j] + gv[(i - 1) % 4][j]) / 2; - } - } - } - - if (!(i % 20) && plistener) { - plistener->setProgress ((double)i / (H - 2)); - } - } - - // finish H-2th and H-1th row, homogenity value is still valailable - int hc, vc; - - for (int i = H - 1; i < H + 1; i++) - for (int j = 0; j < W; j++) { - hc = homh[(i - 1) % 3][j]; - vc = homv[(i - 1) % 3][j]; - - if (hc > vc) { - green[i - 1][j] = gh[(i - 1) % 4][j]; - } else if (hc < vc) { - green[i - 1][j] = gv[(i - 1) % 4][j]; - } else { - green[i - 1][j] = (gh[(i - 1) % 4][j] + gv[(i - 1) % 4][j]) / 2; - } - } - - // Interpolate R and B - for (int i = 0; i < H; i++) { - if (i == 0) { - interpolate_row_rb_mul_pp (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 (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 (red[i], blue[i], green[i - 1], green[i], green[i + 1], i, 1.0, 1.0, 1.0, 0, W, 1); - } - } -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -void RawImageSource::hphd_vertical (float** hpmap, int col_from, int col_to) -{ - float* temp = new float[max(W, H)]; - float* avg = new float[max(W, H)]; - float* dev = new float[max(W, H)]; - - memset (temp, 0, max(W, H)*sizeof(float)); - memset (avg, 0, max(W, H)*sizeof(float)); - memset (dev, 0, max(W, H)*sizeof(float)); - - for (int k = col_from; k < col_to; k++) { - for (int i = 5; i < H - 5; i++) { - temp[i] = (rawData[i - 5][k] - 8 * rawData[i - 4][k] + 27 * rawData[i - 3][k] - 48 * rawData[i - 2][k] + 42 * rawData[i - 1][k] - - (rawData[i + 5][k] - 8 * rawData[i + 4][k] + 27 * rawData[i + 3][k] - 48 * rawData[i + 2][k] + 42 * rawData[i + 1][k])) / 100.0; - temp[i] = ABS(temp[i]); - } - - for (int j = 4; j < H - 4; j++) { - float avgL = (temp[j - 4] + temp[j - 3] + temp[j - 2] + temp[j - 1] + temp[j] + temp[j + 1] + temp[j + 2] + temp[j + 3] + temp[j + 4]) / 9.0; - avg[j] = avgL; - float devL = ((temp[j - 4] - avgL) * (temp[j - 4] - avgL) + (temp[j - 3] - avgL) * (temp[j - 3] - avgL) + (temp[j - 2] - avgL) * (temp[j - 2] - avgL) + (temp[j - 1] - avgL) * (temp[j - 1] - avgL) + (temp[j] - avgL) * (temp[j] - avgL) + (temp[j + 1] - avgL) * (temp[j + 1] - avgL) + (temp[j + 2] - avgL) * (temp[j + 2] - avgL) + (temp[j + 3] - avgL) * (temp[j + 3] - avgL) + (temp[j + 4] - avgL) * (temp[j + 4] - avgL)) / 9.0; - - if (devL < 0.001) { - devL = 0.001; - } - - dev[j] = devL; - } - - for (int j = 5; j < H - 5; j++) { - float avgL = avg[j - 1]; - float avgR = avg[j + 1]; - float devL = dev[j - 1]; - float devR = dev[j + 1]; - hpmap[j][k] = avgL + (avgR - avgL) * devL / (devL + devR); - } - } - - delete [] temp; - delete [] avg; - delete [] dev; -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -void RawImageSource::hphd_horizontal (float** hpmap, int row_from, int row_to) -{ - float* temp = new float[max(W, H)]; - float* avg = new float[max(W, H)]; - float* dev = new float[max(W, H)]; - - memset (temp, 0, max(W, H)*sizeof(float)); - memset (avg, 0, max(W, H)*sizeof(float)); - memset (dev, 0, max(W, H)*sizeof(float)); - - for (int i = row_from; i < row_to; i++) { - for (int j = 5; j < W - 5; j++) { - temp[j] = (rawData[i][j - 5] - 8 * rawData[i][j - 4] + 27 * rawData[i][j - 3] - 48 * rawData[i][j - 2] + 42 * rawData[i][j - 1] - - (rawData[i][j + 5] - 8 * rawData[i][j + 4] + 27 * rawData[i][j + 3] - 48 * rawData[i][j + 2] + 42 * rawData[i][j + 1])) / 100; - temp[j] = ABS(temp[j]); - } - - for (int j = 4; j < W - 4; j++) { - float avgL = (temp[j - 4] + temp[j - 3] + temp[j - 2] + temp[j - 1] + temp[j] + temp[j + 1] + temp[j + 2] + temp[j + 3] + temp[j + 4]) / 9.0; - avg[j] = avgL; - float devL = ((temp[j - 4] - avgL) * (temp[j - 4] - avgL) + (temp[j - 3] - avgL) * (temp[j - 3] - avgL) + (temp[j - 2] - avgL) * (temp[j - 2] - avgL) + (temp[j - 1] - avgL) * (temp[j - 1] - avgL) + (temp[j] - avgL) * (temp[j] - avgL) + (temp[j + 1] - avgL) * (temp[j + 1] - avgL) + (temp[j + 2] - avgL) * (temp[j + 2] - avgL) + (temp[j + 3] - avgL) * (temp[j + 3] - avgL) + (temp[j + 4] - avgL) * (temp[j + 4] - avgL)) / 9.0; - - if (devL < 0.001) { - devL = 0.001; - } - - dev[j] = devL; - } - - for (int j = 5; j < W - 5; j++) { - float avgL = avg[j - 1]; - float avgR = avg[j + 1]; - float devL = dev[j - 1]; - float devR = dev[j + 1]; - float hpv = avgL + (avgR - avgL) * devL / (devL + devR); - - if (hpmap[i][j] < 0.8 * hpv) { - hpmap[i][j] = 2; - } else if (hpv < 0.8 * hpmap[i][j]) { - hpmap[i][j] = 1; - } else { - hpmap[i][j] = 0; - } - } - } - - delete [] temp; - delete [] avg; - delete [] dev; -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -void RawImageSource::hphd_green (float** hpmap) -{ -#ifdef _OPENMP - #pragma omp parallel for -#endif - - for (int i = 3; i < H - 3; i++) { - for (int j = 3; j < W - 3; j++) { - if (ri->ISGREEN(i, j)) { - green[i][j] = rawData[i][j]; - } else { - if (hpmap[i][j] == 1) { - int g2 = rawData[i][j + 1] + ((rawData[i][j] - rawData[i][j + 2]) / 2); - int g4 = rawData[i][j - 1] + ((rawData[i][j] - rawData[i][j - 2]) / 2); - - int dx = rawData[i][j + 1] - rawData[i][j - 1]; - int d1 = rawData[i][j + 3] - rawData[i][j + 1]; - int d2 = rawData[i][j + 2] - rawData[i][j]; - int d3 = (rawData[i - 1][j + 2] - rawData[i - 1][j]) / 2; - int d4 = (rawData[i + 1][j + 2] - rawData[i + 1][j]) / 2; - - double e2 = 1.0 / (1.0 + ABS(dx) + ABS(d1) + ABS(d2) + ABS(d3) + ABS(d4)); - - d1 = rawData[i][j - 3] - rawData[i][j - 1]; - d2 = rawData[i][j - 2] - rawData[i][j]; - d3 = (rawData[i - 1][j - 2] - rawData[i - 1][j]) / 2; - d4 = (rawData[i + 1][j - 2] - rawData[i + 1][j]) / 2; - - double e4 = 1.0 / (1.0 + ABS(dx) + ABS(d1) + ABS(d2) + ABS(d3) + ABS(d4)); - - green[i][j] = (e2 * g2 + e4 * g4) / (e2 + e4); - } else if (hpmap[i][j] == 2) { - int g1 = rawData[i - 1][j] + ((rawData[i][j] - rawData[i - 2][j]) / 2); - int g3 = rawData[i + 1][j] + ((rawData[i][j] - rawData[i + 2][j]) / 2); - - int dy = rawData[i + 1][j] - rawData[i - 1][j]; - int d1 = rawData[i - 1][j] - rawData[i - 3][j]; - int d2 = rawData[i][j] - rawData[i - 2][j]; - int d3 = (rawData[i][j - 1] - rawData[i - 2][j - 1]) / 2; - int d4 = (rawData[i][j + 1] - rawData[i - 2][j + 1]) / 2; - - double e1 = 1.0 / (1.0 + ABS(dy) + ABS(d1) + ABS(d2) + ABS(d3) + ABS(d4)); - - d1 = rawData[i + 1][j] - rawData[i + 3][j]; - d2 = rawData[i][j] - rawData[i + 2][j]; - d3 = (rawData[i][j - 1] - rawData[i + 2][j - 1]) / 2; - d4 = (rawData[i][j + 1] - rawData[i + 2][j + 1]) / 2; - - double e3 = 1.0 / (1.0 + ABS(dy) + ABS(d1) + ABS(d2) + ABS(d3) + ABS(d4)); - - green[i][j] = (e1 * g1 + e3 * g3) / (e1 + e3); - } else { - int g1 = rawData[i - 1][j] + ((rawData[i][j] - rawData[i - 2][j]) / 2); - int g2 = rawData[i][j + 1] + ((rawData[i][j] - rawData[i][j + 2]) / 2); - int g3 = rawData[i + 1][j] + ((rawData[i][j] - rawData[i + 2][j]) / 2); - int g4 = rawData[i][j - 1] + ((rawData[i][j] - rawData[i][j - 2]) / 2); - - int dx = rawData[i][j + 1] - rawData[i][j - 1]; - int dy = rawData[i + 1][j] - rawData[i - 1][j]; - - int d1 = rawData[i - 1][j] - rawData[i - 3][j]; - int d2 = rawData[i][j] - rawData[i - 2][j]; - int d3 = (rawData[i][j - 1] - rawData[i - 2][j - 1]) / 2; - int d4 = (rawData[i][j + 1] - rawData[i - 2][j + 1]) / 2; - - double e1 = 1.0 / (1.0 + ABS(dy) + ABS(d1) + ABS(d2) + ABS(d3) + ABS(d4)); - - d1 = rawData[i][j + 3] - rawData[i][j + 1]; - d2 = rawData[i][j + 2] - rawData[i][j]; - d3 = (rawData[i - 1][j + 2] - rawData[i - 1][j]) / 2; - d4 = (rawData[i + 1][j + 2] - rawData[i + 1][j]) / 2; - - double e2 = 1.0 / (1.0 + ABS(dx) + ABS(d1) + ABS(d2) + ABS(d3) + ABS(d4)); - - d1 = rawData[i + 1][j] - rawData[i + 3][j]; - d2 = rawData[i][j] - rawData[i + 2][j]; - d3 = (rawData[i][j - 1] - rawData[i + 2][j - 1]) / 2; - d4 = (rawData[i][j + 1] - rawData[i + 2][j + 1]) / 2; - - double e3 = 1.0 / (1.0 + ABS(dy) + ABS(d1) + ABS(d2) + ABS(d3) + ABS(d4)); - - d1 = rawData[i][j - 3] - rawData[i][j - 1]; - d2 = rawData[i][j - 2] - rawData[i][j]; - d3 = (rawData[i - 1][j - 2] - rawData[i - 1][j]) / 2; - d4 = (rawData[i + 1][j - 2] - rawData[i + 1][j]) / 2; - - double e4 = 1.0 / (1.0 + ABS(dx) + ABS(d1) + ABS(d2) + ABS(d3) + ABS(d4)); - - green[i][j] = (e1 * g1 + e2 * g2 + e3 * g3 + e4 * g4) / (e1 + e2 + e3 + e4); - } - } - } - } -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -void RawImageSource::hphd_demosaic () -{ - if (plistener) { - plistener->setProgressStr (Glib::ustring::compose(M("TP_RAW_DMETHOD_PROGRESSBAR"), RAWParams::BayerSensor::getMethodString(RAWParams::BayerSensor::Method::HPHD))); - plistener->setProgress (0.0); - } - - JaggedArray hpmap (W, H, true); - -#ifdef _OPENMP - #pragma omp parallel - { - int tid = omp_get_thread_num(); - int nthreads = omp_get_num_threads(); - int blk = W / nthreads; - - if (tid < nthreads - 1) { - hphd_vertical (hpmap, tid * blk, (tid + 1)*blk); - } else { - hphd_vertical (hpmap, tid * blk, W); - } - } -#else - hphd_vertical (hpmap, 0, W); -#endif - - if (plistener) { - plistener->setProgress (0.33); - } - -#ifdef _OPENMP - #pragma omp parallel - { - int tid = omp_get_thread_num(); - int nthreads = omp_get_num_threads(); - int blk = H / nthreads; - - if (tid < nthreads - 1) { - hphd_horizontal (hpmap, tid * blk, (tid + 1)*blk); - } else { - hphd_horizontal (hpmap, tid * blk, H); - } - } -#else - hphd_horizontal (hpmap, 0, H); -#endif - - hphd_green (hpmap); - - if (plistener) { - plistener->setProgress (0.66); - } - - for (int i = 0; i < H; i++) { - if (i == 0) { - interpolate_row_rb_mul_pp (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 (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 (red[i], blue[i], green[i - 1], green[i], green[i + 1], i, 1.0, 1.0, 1.0, 0, W, 1); - } - } - - if (plistener) { - plistener->setProgress (1.0); - } -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -#define fc(row,col) (prefilters >> ((((row) << 1 & 14) + ((col) & 1)) << 1) & 3) -typedef unsigned short ushort; -void RawImageSource::vng4_demosaic () -{ - const signed short int *cp, terms[] = { - -2, -2, +0, -1, 0, 0x01, -2, -2, +0, +0, 1, 0x01, -2, -1, -1, +0, 0, 0x01, - -2, -1, +0, -1, 0, 0x02, -2, -1, +0, +0, 0, 0x03, -2, -1, +0, +1, 1, 0x01, - -2, +0, +0, -1, 0, 0x06, -2, +0, +0, +0, 1, 0x02, -2, +0, +0, +1, 0, 0x03, - -2, +1, -1, +0, 0, 0x04, -2, +1, +0, -1, 1, 0x04, -2, +1, +0, +0, 0, 0x06, - -2, +1, +0, +1, 0, 0x02, -2, +2, +0, +0, 1, 0x04, -2, +2, +0, +1, 0, 0x04, - -1, -2, -1, +0, 0, 0x80, -1, -2, +0, -1, 0, 0x01, -1, -2, +1, -1, 0, 0x01, - -1, -2, +1, +0, 1, 0x01, -1, -1, -1, +1, 0, 0x88, -1, -1, +1, -2, 0, 0x40, - -1, -1, +1, -1, 0, 0x22, -1, -1, +1, +0, 0, 0x33, -1, -1, +1, +1, 1, 0x11, - -1, +0, -1, +2, 0, 0x08, -1, +0, +0, -1, 0, 0x44, -1, +0, +0, +1, 0, 0x11, - -1, +0, +1, -2, 1, 0x40, -1, +0, +1, -1, 0, 0x66, -1, +0, +1, +0, 1, 0x22, - -1, +0, +1, +1, 0, 0x33, -1, +0, +1, +2, 1, 0x10, -1, +1, +1, -1, 1, 0x44, - -1, +1, +1, +0, 0, 0x66, -1, +1, +1, +1, 0, 0x22, -1, +1, +1, +2, 0, 0x10, - -1, +2, +0, +1, 0, 0x04, -1, +2, +1, +0, 1, 0x04, -1, +2, +1, +1, 0, 0x04, - +0, -2, +0, +0, 1, 0x80, +0, -1, +0, +1, 1, 0x88, +0, -1, +1, -2, 0, 0x40, - +0, -1, +1, +0, 0, 0x11, +0, -1, +2, -2, 0, 0x40, +0, -1, +2, -1, 0, 0x20, - +0, -1, +2, +0, 0, 0x30, +0, -1, +2, +1, 1, 0x10, +0, +0, +0, +2, 1, 0x08, - +0, +0, +2, -2, 1, 0x40, +0, +0, +2, -1, 0, 0x60, +0, +0, +2, +0, 1, 0x20, - +0, +0, +2, +1, 0, 0x30, +0, +0, +2, +2, 1, 0x10, +0, +1, +1, +0, 0, 0x44, - +0, +1, +1, +2, 0, 0x10, +0, +1, +2, -1, 1, 0x40, +0, +1, +2, +0, 0, 0x60, - +0, +1, +2, +1, 0, 0x20, +0, +1, +2, +2, 0, 0x10, +1, -2, +1, +0, 0, 0x80, - +1, -1, +1, +1, 0, 0x88, +1, +0, +1, +2, 0, 0x08, +1, +0, +2, -1, 0, 0x40, - +1, +0, +2, +1, 0, 0x10 - }, - chood[] = { -1, -1, -1, 0, -1, +1, 0, +1, +1, +1, +1, 0, +1, -1, 0, -1 }; - - double progress = 0.0; - const bool plistenerActive = plistener; - - if (plistenerActive) { - plistener->setProgressStr (Glib::ustring::compose(M("TP_RAW_DMETHOD_PROGRESSBAR"), RAWParams::BayerSensor::getMethodString(RAWParams::BayerSensor::Method::VNG4))); - plistener->setProgress (progress); - } - - const unsigned prefilters = ri->prefilters; - const int width = W, height = H; - constexpr unsigned int colors = 4; - float (*image)[4]; - - image = (float (*)[4]) calloc (height * width, sizeof * image); - -#ifdef _OPENMP - #pragma omp parallel for -#endif - - for (int ii = 0; ii < H; ii++) - for (int jj = 0; jj < W; jj++) { - image[ii * W + jj][fc(ii, jj)] = rawData[ii][jj]; - } - - { - int lcode[16][16][32]; - float mul[16][16][8]; - float csum[16][16][4]; - -// first linear interpolation - for (int row = 0; row < 16; row++) - for (int col = 0; col < 16; col++) { - int * ip = lcode[row][col]; - int mulcount = 0; - float sum[4]; - memset (sum, 0, sizeof sum); - - for (int y = -1; y <= 1; y++) - for (int x = -1; x <= 1; x++) { - int shift = (y == 0) + (x == 0); - - if (shift == 2) { - continue; - } - - int color = fc(row + y, col + x); - *ip++ = (width * y + x) * 4 + color; - - mul[row][col][mulcount] = (1 << shift); - *ip++ = color; - sum[color] += (1 << shift); - mulcount++; - } - - int colcount = 0; - - for (unsigned int c = 0; c < colors; c++) - if (c != fc(row, col)) { - *ip++ = c; - csum[row][col][colcount] = sum[c]; - colcount ++; - } - } - -StopWatch Stop1("loop 1"); -#ifdef _OPENMP - #pragma omp parallel for -#endif - - for (int row = 1; row < height - 1; row++) { - 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); - - 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]; - } - } - } -Stop1.stop(); - } - const int prow = 7, pcol = 1; - int *code[8][2]; - int t, g; - int * ip = (int *) calloc ((prow + 1) * (pcol + 1), 1280); - - for (int row = 0; row <= prow; row++) /* Precalculate for VNG */ - for (int col = 0; col <= pcol; col++) { - code[row][col] = ip; - - for (cp = terms, t = 0; t < 64; t++) { - int y1 = *cp++; - int x1 = *cp++; - int y2 = *cp++; - int x2 = *cp++; - int weight = *cp++; - int grads = *cp++; - unsigned int color = fc(row + y1, col + x1); - - if (fc(row + y2, col + x2) != color) { - continue; - } - - int diag = (fc(row, col + 1) == color && fc(row + 1, col) == color) ? 2 : 1; - - if (abs(y1 - y2) == diag && abs(x1 - x2) == diag) { - continue; - } - - *ip++ = (y1 * width + x1) * 4 + color; - *ip++ = (y2 * width + x2) * 4 + color; - *ip++ = weight; - - for (g = 0; g < 8; g++) - if (grads & (1 << g)) { - *ip++ = g; - } - - *ip++ = -1; - } - - *ip++ = INT_MAX; - - for (cp = chood, g = 0; g < 8; g++) { - int y = *cp++; - int x = *cp++; - *ip++ = (y * width + x) * 4; - unsigned int color = fc(row, col); - - if (fc(row + y, col + x) != color && fc(row + y * 2, col + x * 2) == color) { - *ip++ = (y * width + x) * 8 + color; - } else { - *ip++ = 0; - } - } - } - - if(plistenerActive) { - progress = 0.1; - plistener->setProgress (progress); - } - -StopWatch Stop2("loop 2"); - -#ifdef _OPENMP - #pragma omp parallel -#endif - { - float thold; - int g; - constexpr int progressStep = 64; - const double progressInc = (0.98 - progress) / ((height - 2) / progressStep); -#ifdef _OPENMP - #pragma omp for schedule(dynamic,16) nowait -#endif - - for (int row = 2; row < height - 2; row++) { /* Do VNG interpolation */ - for (int col = 2; col < width - 2; col++) { - float * pix = image[row * width + col]; - int * ip = code[row & prow][col & pcol]; - float gval[8] = {}; -// gval[0] = gval[1] = gval[2] = gval[3] = gval[4] = gval[5] = gval[6] = gval[7] = 0.f; -// memset (gval, 0, sizeof gval); - - while ((g = ip[0]) != INT_MAX) { /* Calculate gradients */ - float diff = fabsf(pix[g] - pix[ip[1]]) * (1 << ip[2]); - gval[ip[3]] += diff; - ip += 4; - - while ((g = *ip++) != -1) { - gval[g] += diff; - } - } - - ip++; - { - float gmin, gmax; - gmin = gmax = gval[0]; /* Choose a threshold */ - - for (g = 1; g < 8; g++) { - gmin = rtengine::min(gmin, gval[g]); -// if (gmin > gval[g]) { -// gmin = gval[g]; -// } - - gmax = rtengine::max(gmax, gval[g]); -// if (gmax < gval[g]) { -// gmax = gval[g]; -// } - } - - thold = gmin + (gmax / 2); - } - float sum[3] = {}; -// sum[0] = sum[1] = sum[2] = 0.f; -// memset (sum, 0, sizeof sum); - float t1, t2; - int color = fc(row, col); - t1 = t2 = pix[color]; - - if(color & 1) { - int num = 0; - - for (g = 0; g < 8; g++, ip += 2) { /* Average the neighbors */ - if (gval[g] <= thold) { - if(ip[1]) { - sum[0] += (t1 + pix[ip[1]]) * 0.5f; - } - - sum[1] += pix[ip[0] + (color ^ 2)]; - num++; - } - } - - t1 += (sum[1] - sum[0]) / num; - } else { - int num = 0; - - for (g = 0; g < 8; g++, ip += 2) { /* Average the neighbors */ - if (gval[g] <= thold) { - sum[1] += pix[ip[0] + 1]; - sum[2] += pix[ip[0] + 3]; - - if(ip[1]) { - sum[0] += (t1 + pix[ip[1]]) * 0.5f; - } - - num++; - } - } - - t1 += (sum[1] - sum[0]) / num; - t2 += (sum[2] - sum[0]) / num; - } - - green[row][col] = 0.5f * (t1 + t2); - } - - if(plistenerActive) { - if((row % progressStep) == 0) -#ifdef _OPENMP - #pragma omp critical (updateprogress) -#endif - { - progress += progressInc; - plistener->setProgress (progress); - } - } - } - - } -Stop2.stop(); - free (code[0][0]); - free (image); - - if(plistenerActive) { - plistener->setProgress (0.98); - } -StopWatch Stop3("loop 3"); - - // 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 (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 (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 (red[i], blue[i], green[i - 1], green[i], green[i + 1], i, 1.0, 1.0, 1.0, 0, W, 1); - } - } -Stop3.stop(); - if(plistenerActive) { - plistener->setProgress (1.0); - } -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -#undef fc -#define fc(row,col) \ - (ri->get_filters() >> ((((row) << 1 & 14) + ((col) & 1)) << 1) & 3) - -#define FORCC for (unsigned int c=0; c < colors; c++) - -/* - Patterned Pixel Grouping Interpolation by Alain Desbiolles -*/ -void RawImageSource::ppg_demosaic() -{ - int width = W, height = H; - int dir[5] = { 1, width, -1, -width, 1 }; - int row, col, diff[2] = {}, guess[2], c, d, i; - float (*pix)[4]; - - float (*image)[4]; - - if (plistener) { - // looks like ppg isn't supported anymore - //plistener->setProgressStr (Glib::ustring::compose(M("TP_RAW_DMETHOD_PROGRESSBAR"), RAWParams::BayerSensor::getMethodString(RAWParams::BayerSensor::ppg))); - plistener->setProgressStr (Glib::ustring::compose(M("TP_RAW_DMETHOD_PROGRESSBAR"), "xxx")); - plistener->setProgress (0.0); - } - - image = (float (*)[4]) calloc (H * W, sizeof * image); - - for (int ii = 0; ii < H; ii++) - for (int jj = 0; jj < W; jj++) { - image[ii * W + jj][fc(ii, jj)] = rawData[ii][jj]; - } - - border_interpolate(3, image); - - /* Fill in the green layer with gradients and pattern recognition: */ - for (row = 3; row < height - 3; row++) { - for (col = 3 + (FC(row, 3) & 1), c = FC(row, col); col < width - 3; col += 2) { - pix = image + row * width + col; - - for (i = 0; (d = dir[i]) > 0; i++) { - guess[i] = (pix[-d][1] + pix[0][c] + pix[d][1]) * 2 - - pix[-2 * d][c] - pix[2 * d][c]; - diff[i] = ( ABS(pix[-2 * d][c] - pix[ 0][c]) + - ABS(pix[ 2 * d][c] - pix[ 0][c]) + - ABS(pix[ -d][1] - pix[ d][1]) ) * 3 + - ( ABS(pix[ 3 * d][1] - pix[ d][1]) + - ABS(pix[-3 * d][1] - pix[-d][1]) ) * 2; - } - - d = dir[i = diff[0] > diff[1]]; - pix[0][1] = median(static_cast(guess[i] >> 2), pix[d][1], pix[-d][1]); - } - - if(plistener) { - plistener->setProgress(0.33 * row / (height - 3)); - } - } - - /* Calculate red and blue for each green pixel: */ - for (row = 1; row < height - 1; row++) { - for (col = 1 + (FC(row, 2) & 1), c = FC(row, col + 1); col < width - 1; col += 2) { - pix = image + row * width + col; - - for (i = 0; (d = dir[i]) > 0; c = 2 - c, i++) - pix[0][c] = CLIP(0.5 * (pix[-d][c] + pix[d][c] + 2 * pix[0][1] - - pix[-d][1] - pix[d][1]) ); - } - - if(plistener) { - plistener->setProgress(0.33 + 0.33 * row / (height - 1)); - } - } - - /* Calculate blue for red pixels and vice versa: */ - for (row = 1; row < height - 1; row++) { - for (col = 1 + (FC(row, 1) & 1), c = 2 - FC(row, col); col < width - 1; col += 2) { - pix = image + row * width + col; - - for (i = 0; (d = dir[i] + dir[i + 1]) > 0; i++) { - diff[i] = ABS(pix[-d][c] - pix[d][c]) + - ABS(pix[-d][1] - pix[0][1]) + - ABS(pix[ d][1] - pix[0][1]); - guess[i] = pix[-d][c] + pix[d][c] + 2 * pix[0][1] - - pix[-d][1] - pix[d][1]; - } - - if (diff[0] != diff[1]) { - pix[0][c] = CLIP(guess[diff[0] > diff[1]] / 2); - } else { - pix[0][c] = CLIP((guess[0] + guess[1]) / 4); - } - } - - if(plistener) { - plistener->setProgress(0.67 + 0.33 * row / (height - 1)); - } - } - - red(W, H); - - for (int i = 0; i < H; i++) - for (int j = 0; j < W; j++) { - red[i][j] = image[i * W + j][0]; - } - - green(W, H); - - for (int i = 0; i < H; i++) - for (int j = 0; j < W; j++) { - green[i][j] = image[i * W + j][1]; - } - - blue(W, H); - - for (int i = 0; i < H; i++) - for (int j = 0; j < W; j++) { - blue[i][j] = image[i * W + j][2]; - } - - free (image); -} - -void RawImageSource::border_interpolate(unsigned int border, float (*image)[4], unsigned int start, unsigned int end) -{ - unsigned row, col, y, x, f, sum[8]; - unsigned int width = W, height = H; - unsigned int colors = 3; - - if (end == 0 ) { - end = H; - } - - for (row = start; row < end; row++) - for (col = 0; col < width; col++) { - if (col == border && row >= border && row < height - border) { - col = width - border; - } - - memset (sum, 0, sizeof sum); - - for (y = row - 1; y != row + 2; y++) - for (x = col - 1; x != col + 2; x++) - if (y < height && x < width) { - f = fc(y, x); - sum[f] += image[y * width + x][f]; - sum[f + 4]++; - } - - f = fc(row, col); - - FORCC if (c != f && sum[c + 4]) { - image[row * width + col][c] = sum[c] / sum[c + 4]; - } - } -} - -void RawImageSource::border_interpolate2( int winw, int winh, int lborders) -{ - int bord = lborders; - int width = winw; - int height = winh; - - for (int i = 0; i < height; i++) { - - float sum[6]; - - for (int j = 0; j < bord; j++) { //first few columns - for (int c = 0; c < 6; c++) { - sum[c] = 0; - } - - for (int i1 = i - 1; i1 < i + 2; i1++) - for (int j1 = j - 1; j1 < j + 2; j1++) { - if ((i1 > -1) && (i1 < height) && (j1 > -1)) { - int c = FC(i1, j1); - sum[c] += rawData[i1][j1]; - sum[c + 3]++; - } - } - - int c = FC(i, j); - - if (c == 1) { - red[i][j] = sum[0] / sum[3]; - green[i][j] = rawData[i][j]; - blue[i][j] = sum[2] / sum[5]; - } else { - green[i][j] = sum[1] / sum[4]; - - if (c == 0) { - red[i][j] = rawData[i][j]; - blue[i][j] = sum[2] / sum[5]; - } else { - red[i][j] = sum[0] / sum[3]; - blue[i][j] = rawData[i][j]; - } - } - }//j - - for (int j = width - bord; j < width; j++) { //last few columns - for (int c = 0; c < 6; c++) { - sum[c] = 0; - } - - for (int i1 = i - 1; i1 < i + 2; i1++) - for (int j1 = j - 1; j1 < j + 2; j1++) { - if ((i1 > -1) && (i1 < height ) && (j1 < width)) { - int c = FC(i1, j1); - sum[c] += rawData[i1][j1]; - sum[c + 3]++; - } - } - - int c = FC(i, j); - - if (c == 1) { - red[i][j] = sum[0] / sum[3]; - green[i][j] = rawData[i][j]; - blue[i][j] = sum[2] / sum[5]; - } else { - green[i][j] = sum[1] / sum[4]; - - if (c == 0) { - red[i][j] = rawData[i][j]; - blue[i][j] = sum[2] / sum[5]; - } else { - red[i][j] = sum[0] / sum[3]; - blue[i][j] = rawData[i][j]; - } - } - }//j - }//i - - for (int i = 0; i < bord; i++) { - - float sum[6]; - - for (int j = bord; j < width - bord; j++) { //first few rows - for (int c = 0; c < 6; c++) { - sum[c] = 0; - } - - for (int i1 = i - 1; i1 < i + 2; i1++) - for (int j1 = j - 1; j1 < j + 2; j1++) { - if ((i1 > -1) && (i1 < height) && (j1 > -1)) { - int c = FC(i1, j1); - sum[c] += rawData[i1][j1]; - sum[c + 3]++; - } - } - - int c = FC(i, j); - - if (c == 1) { - red[i][j] = sum[0] / sum[3]; - green[i][j] = rawData[i][j]; - blue[i][j] = sum[2] / sum[5]; - } else { - green[i][j] = sum[1] / sum[4]; - - if (c == 0) { - red[i][j] = rawData[i][j]; - blue[i][j] = sum[2] / sum[5]; - } else { - red[i][j] = sum[0] / sum[3]; - blue[i][j] = rawData[i][j]; - } - } - }//j - } - - for (int i = height - bord; i < height; i++) { - - float sum[6]; - - for (int j = bord; j < width - bord; j++) { //last few rows - for (int c = 0; c < 6; c++) { - sum[c] = 0; - } - - for (int i1 = i - 1; i1 < i + 2; i1++) - for (int j1 = j - 1; j1 < j + 2; j1++) { - if ((i1 > -1) && (i1 < height) && (j1 < width)) { - int c = FC(i1, j1); - sum[c] += rawData[i1][j1]; - sum[c + 3]++; - } - } - - int c = FC(i, j); - - if (c == 1) { - red[i][j] = sum[0] / sum[3]; - green[i][j] = rawData[i][j]; - blue[i][j] = sum[2] / sum[5]; - } else { - green[i][j] = sum[1] / sum[4]; - - if (c == 0) { - red[i][j] = rawData[i][j]; - blue[i][j] = sum[2] / sum[5]; - } else { - red[i][j] = sum[0] / sum[3]; - blue[i][j] = rawData[i][j]; - } - } - }//j - } - -} - -// Joint Demosaicing and Denoising using High Order Interpolation Techniques -// Revision 0.9.1a - 09/02/2010 - Contact info: luis.sanz.rodriguez@gmail.com -// Copyright Luis Sanz Rodriguez 2010 -// Adapted to RawTherapee by Jacques Desmis 3/2013 - -void RawImageSource::jdl_interpolate_omp() // from "Lassus" -{ - int width = W, height = H; - int row, col, c, d, i, u = width, v = 2 * u, w = 3 * u, x = 4 * u, y = 5 * u, z = 6 * u, indx, (*dif)[2], (*chr)[2]; - float f[4], g[4]; - float (*image)[4]; - image = (float (*)[4]) calloc (width * height, sizeof * image); - dif = (int (*)[2]) calloc(width * height, sizeof * dif); - chr = (int (*)[2]) calloc(width * height, sizeof * chr); - - if (plistener) { - // this function seems to be unused - //plistener->setProgressStr (Glib::ustring::compose(M("TP_RAW_DMETHOD_PROGRESSBAR"), RAWParams::BayerSensor::getMethodString(RAWParams::BayerSensor::jdl))); - plistener->setProgressStr (Glib::ustring::compose(M("TP_RAW_DMETHOD_PROGRESSBAR"), "xxx")); - plistener->setProgress (0.0); - } - -#ifdef _OPENMP - #pragma omp parallel default(none) shared(image,width,height,u,w,v,y,x,z,dif,chr) private(row,col,f,g,indx,c,d,i) -#endif - { -#ifdef _OPENMP - #pragma omp for -#endif - - for (int ii = 0; ii < height; ii++) - for (int jj = 0; jj < width; jj++) { - image[ii * width + jj][fc(ii, jj)] = rawData[ii][jj]; - } - - border_interpolate(6, image); - -#ifdef _OPENMP - #pragma omp for -#endif - - for (row = 5; row < height - 5; row++) - for (col = 5 + (FC(row, 1) & 1), indx = row * width + col, c = FC(row, col); col < u - 5; col += 2, indx += 2) { - f[0] = 1.f + abs(image[indx - u][1] - image[indx - w][1]) + abs(image[indx - u][1] - image[indx + u][1]) + abs(image[indx][c] - image[indx - v][c]) + abs(image[indx - v][c] - image[indx - x][c]); - f[1] = 1.f + abs(image[indx + 1][1] - image[indx + 3][1]) + abs(image[indx + 1][1] - image[indx - 1][1]) + abs(image[indx][c] - image[indx + 2][c]) + abs(image[indx + 2][c] - image[indx + 4][c]); - f[2] = 1.f + abs(image[indx - 1][1] - image[indx - 3][1]) + abs(image[indx - 1][1] - image[indx + 1][1]) + abs(image[indx][c] - image[indx - 2][c]) + abs(image[indx - 2][c] - image[indx - 4][c]); - f[3] = 1.f + abs(image[indx + u][1] - image[indx + w][1]) + abs(image[indx + u][1] - image[indx - u][1]) + abs(image[indx][c] - image[indx + v][c]) + abs(image[indx + v][c] - image[indx + x][c]); - g[0] = CLIP((22.f * image[indx - u][1] + 22.f * image[indx - w][1] + 2.f * image[indx - y][1] + 2.f * image[indx + u][1] + 40.f * image[indx][c] - 32.f * image[indx - v][c] - 8.f * image[indx - x][c]) / 48.f); - g[1] = CLIP((22.f * image[indx + 1][1] + 22.f * image[indx + 3][1] + 2.f * image[indx + 5][1] + 2.f * image[indx - 1][1] + 40.f * image[indx][c] - 32.f * image[indx + 2][c] - 8.f * image[indx + 4][c]) / 48.f); - g[2] = CLIP((22.f * image[indx - 1][1] + 22.f * image[indx - 3][1] + 2.f * image[indx - 5][1] + 2.f * image[indx + 1][1] + 40.f * image[indx][c] - 32.f * image[indx - 2][c] - 8.f * image[indx - 4][c]) / 48.f); - g[3] = CLIP((22.f * image[indx + u][1] + 22.f * image[indx + w][1] + 2.f * image[indx + y][1] + 2.f * image[indx - u][1] + 40.f * image[indx][c] - 32.f * image[indx + v][c] - 8.f * image[indx + x][c]) / 48.f); - dif[indx][0] = CLIP((f[3] * g[0] + f[0] * g[3]) / (f[0] + f[3])) - image[indx][c]; - dif[indx][1] = CLIP((f[2] * g[1] + f[1] * g[2]) / (f[1] + f[2])) - image[indx][c]; - } - -#ifdef _OPENMP - #pragma omp for -#endif - - for (row = 6; row < height - 6; row++) - for (col = 6 + (FC(row, 2) & 1), indx = row * width + col, c = FC(row, col) / 2; col < u - 6; col += 2, indx += 2) { - f[0] = 1.f + 78.f * SQR((float)dif[indx][0]) + 69.f * (SQR((float) dif[indx - v][0]) + SQR((float)dif[indx + v][0])) + 51.f * (SQR((float)dif[indx - x][0]) + SQR((float)dif[indx + x][0])) + 21.f * (SQR((float)dif[indx - z][0]) + SQR((float)dif[indx + z][0])) - 6.f * SQR((float)dif[indx - v][0] + dif[indx][0] + dif[indx + v][0]) - 10.f * (SQR((float)dif[indx - x][0] + dif[indx - v][0] + dif[indx][0]) + SQR((float)dif[indx][0] + dif[indx + v][0] + dif[indx + x][0])) - 7.f * (SQR((float)dif[indx - z][0] + dif[indx - x][0] + dif[indx - v][0]) + SQR((float)dif[indx + v][0] + dif[indx + x][0] + dif[indx + z][0])); - f[1] = 1.f + 78.f * SQR((float)dif[indx][1]) + 69.f * (SQR((float)dif[indx - 2][1]) + SQR((float)dif[indx + 2][1])) + 51.f * (SQR((float)dif[indx - 4][1]) + SQR((float)dif[indx + 4][1])) + 21.f * (SQR((float)dif[indx - 6][1]) + SQR((float)dif[indx + 6][1])) - 6.f * SQR((float)dif[indx - 2][1] + dif[indx][1] + dif[indx + 2][1]) - 10.f * (SQR((float)dif[indx - 4][1] + dif[indx - 2][1] + dif[indx][1]) + SQR((float)dif[indx][1] + dif[indx + 2][1] + dif[indx + 4][1])) - 7.f * (SQR((float)dif[indx - 6][1] + dif[indx - 4][1] + dif[indx - 2][1]) + SQR((float)dif[indx + 2][1] + dif[indx + 4][1] + dif[indx + 6][1])); - g[0] = median(0.725f * dif[indx][0] + 0.1375f * dif[indx - v][0] + 0.1375f * dif[indx + v][0], static_cast(dif[indx - v][0]), static_cast(dif[indx + v][0])); - g[1] = median(0.725f * dif[indx][1] + 0.1375f * dif[indx - 2][1] + 0.1375f * dif[indx + 2][1], static_cast(dif[indx - 2][1]), static_cast(dif[indx + 2][1])); - chr[indx][c] = (f[1] * g[0] + f[0] * g[1]) / (f[0] + f[1]); - } - -#ifdef _OPENMP - #pragma omp for -#endif - - for (row = 6; row < height - 6; row++) - for (col = 6 + (FC(row, 2) & 1), indx = row * width + col, c = 1 - FC(row, col) / 2, d = 2 * c; col < u - 6; col += 2, indx += 2) { - f[0] = 1.f / (float)(1.f + fabs((float)chr[indx - u - 1][c] - chr[indx + u + 1][c]) + fabs((float)chr[indx - u - 1][c] - chr[indx - w - 3][c]) + fabs((float)chr[indx + u + 1][c] - chr[indx - w - 3][c])); - f[1] = 1.f / (float)(1.f + fabs((float)chr[indx - u + 1][c] - chr[indx + u - 1][c]) + fabs((float)chr[indx - u + 1][c] - chr[indx - w + 3][c]) + fabs((float)chr[indx + u - 1][c] - chr[indx - w + 3][c])); - f[2] = 1.f / (float)(1.f + fabs((float)chr[indx + u - 1][c] - chr[indx - u + 1][c]) + fabs((float)chr[indx + u - 1][c] - chr[indx + w + 3][c]) + fabs((float)chr[indx - u + 1][c] - chr[indx + w - 3][c])); - f[3] = 1.f / (float)(1.f + fabs((float)chr[indx + u + 1][c] - chr[indx - u - 1][c]) + fabs((float)chr[indx + u + 1][c] - chr[indx + w - 3][c]) + fabs((float)chr[indx - u - 1][c] - chr[indx + w + 3][c])); - g[0] = median(chr[indx - u - 1][c], chr[indx - w - 1][c], chr[indx - u - 3][c]); - g[1] = median(chr[indx - u + 1][c], chr[indx - w + 1][c], chr[indx - u + 3][c]); - g[2] = median(chr[indx + u - 1][c], chr[indx + w - 1][c], chr[indx + u - 3][c]); - g[3] = median(chr[indx + u + 1][c], chr[indx + w + 1][c], chr[indx + u + 3][c]); - chr[indx][c] = (f[0] * g[0] + f[1] * g[1] + f[2] * g[2] + f[3] * g[3]) / (f[0] + f[1] + f[2] + f[3]); - image[indx][1] = CLIP(image[indx][2 - d] + chr[indx][1 - c]); - image[indx][d] = CLIP(image[indx][1] - chr[indx][c]); - } - -#ifdef _OPENMP - #pragma omp for -#endif - - for (row = 6; row < height - 6; row++) - for (col = 6 + (FC(row, 1) & 1), indx = row * width + col, c = FC(row, col + 1) / 2, d = 2 * c; col < u - 6; col += 2, indx += 2) - for(i = 0; i <= 1; c = 1 - c, d = 2 * c, i++) { - f[0] = 1.f / (float)(1.f + fabs((float)chr[indx - u][c] - chr[indx + u][c]) + fabs((float)chr[indx - u][c] - chr[indx - w][c]) + fabs((float)chr[indx + u][c] - chr[indx - w][c])); - f[1] = 1.f / (float)(1.f + fabs((float)chr[indx + 1][c] - chr[indx - 1][c]) + fabs((float)chr[indx + 1][c] - chr[indx + 3][c]) + fabs((float)chr[indx - 1][c] - chr[indx + 3][c])); - f[2] = 1.f / (float)(1.f + fabs((float)chr[indx - 1][c] - chr[indx + 1][c]) + fabs((float)chr[indx - 1][c] - chr[indx - 3][c]) + fabs((float)chr[indx + 1][c] - chr[indx - 3][c])); - f[3] = 1.f / (float)(1.f + fabs((float)chr[indx + u][c] - chr[indx - u][c]) + fabs((float)chr[indx + u][c] - chr[indx + w][c]) + fabs((float)chr[indx - u][c] - chr[indx + w][c])); - g[0] = 0.875f * chr[indx - u][c] + 0.125f * chr[indx - w][c]; - g[1] = 0.875f * chr[indx + 1][c] + 0.125f * chr[indx + 3][c]; - g[2] = 0.875f * chr[indx - 1][c] + 0.125f * chr[indx - 3][c]; - g[3] = 0.875f * chr[indx + u][c] + 0.125f * chr[indx + w][c]; - image[indx][d] = CLIP(image[indx][1] - (f[0] * g[0] + f[1] * g[1] + f[2] * g[2] + f[3] * g[3]) / (f[0] + f[1] + f[2] + f[3])); - } - -#ifdef _OPENMP - #pragma omp for -#endif - - for (int ii = 0; ii < height; ii++) { - for (int jj = 0; jj < width; jj++) { - red[ii][jj] = CLIP(image[ii * width + jj][0]); - green[ii][jj] = CLIP(image[ii * width + jj][1]); - blue[ii][jj] = CLIP(image[ii * width + jj][2]); - } - } - } // End of parallelization - free (image); - free(dif); - free(chr); - //RawImageSource::refinement_lassus(); -} - -// LSMME demosaicing algorithm -// L. Zhang and X. Wu, -// Color demozaicing via directional Linear Minimum Mean Square-error Estimation, -// IEEE Trans. on Image Processing, vol. 14, pp. 2167-2178, -// Dec. 2005. -// Adapted to RawTherapee by Jacques Desmis 3/2013 -// Improved speed and reduced memory consumption by Ingo Weyrich 2/2015 -//TODO Tiles to reduce memory consumption -void RawImageSource::lmmse_interpolate_omp(int winw, int winh, array2D &rawData, array2D &red, array2D &green, array2D &blue, int iterations) -{ - const int width = winw, height = winh; - const int ba = 10; - const int rr1 = height + 2 * ba; - const int cc1 = width + 2 * ba; - const int w1 = cc1; - const int w2 = 2 * w1; - const int w3 = 3 * w1; - const int w4 = 4 * w1; - float h0, h1, h2, h3, h4, hs; - h0 = 1.0f; - h1 = exp( -1.0f / 8.0f); - h2 = exp( -4.0f / 8.0f); - h3 = exp( -9.0f / 8.0f); - h4 = exp(-16.0f / 8.0f); - hs = h0 + 2.0f * (h1 + h2 + h3 + h4); - h0 /= hs; - h1 /= hs; - h2 /= hs; - h3 /= hs; - h4 /= hs; - int passref = 0; - int iter = 0; - - if(iterations <= 4) { - iter = iterations - 1; - passref = 0; - } else if (iterations <= 6) { - iter = 3; - passref = iterations - 4; - } else if (iterations <= 8) { - iter = 3; - passref = iterations - 6; - } - - bool applyGamma = true; - - if(iterations == 0) { - applyGamma = false; - iter = 0; - } else { - applyGamma = true; - } - - float *rix[5]; - float *qix[5]; - float *buffer = (float *)calloc(rr1 * cc1 * 5 * sizeof(float), 1); - - if(buffer == nullptr) { // allocation of big block of memory failed, try to get 5 smaller ones - printf("lmmse_interpolate_omp: allocation of big memory block failed, try to get 5 smaller ones now...\n"); - bool allocationFailed = false; - - for(int i = 0; i < 5; i++) { - qix[i] = (float *)calloc(rr1 * cc1 * sizeof(float), 1); - - if(!qix[i]) { // allocation of at least one small block failed - allocationFailed = true; - } - } - - if(allocationFailed) { // fall back to igv_interpolate - printf("lmmse_interpolate_omp: allocation of 5 small memory blocks failed, falling back to igv_interpolate...\n"); - - for(int i = 0; i < 5; i++) { // free the already allocated buffers - if(qix[i]) { - free(qix[i]); - } - } - - igv_interpolate(winw, winh); - return; - } - } else { - qix[0] = buffer; - - for(int i = 1; i < 5; i++) { - qix[i] = qix[i - 1] + rr1 * cc1; - } - } - - if (plistener) { - plistener->setProgressStr (Glib::ustring::compose(M("TP_RAW_DMETHOD_PROGRESSBAR"), RAWParams::BayerSensor::getMethodString(RAWParams::BayerSensor::Method::LMMSE))); - plistener->setProgress (0.0); - } - - - LUTf *gamtab; - - if(applyGamma) { - gamtab = &(Color::gammatab_24_17a); - } else { - gamtab = new LUTf(65536, LUT_CLIP_ABOVE | LUT_CLIP_BELOW); - gamtab->makeIdentity(65535.f); - } - - -#ifdef _OPENMP - #pragma omp parallel private(rix) -#endif - { -#ifdef _OPENMP - #pragma omp for -#endif - - for (int rrr = ba; rrr < rr1 - ba; rrr++) { - for (int ccc = ba, row = rrr - ba; ccc < cc1 - ba; ccc++) { - int col = ccc - ba; - float *rix = qix[4] + rrr * cc1 + ccc; - rix[0] = (*gamtab)[rawData[row][col]]; - } - } - -#ifdef _OPENMP - #pragma omp single -#endif - { - if (plistener) { - plistener->setProgress (0.1); - } - } - - // G-R(B) -#ifdef _OPENMP - #pragma omp for schedule(dynamic,16) -#endif - - for (int rr = 2; rr < rr1 - 2; rr++) { - // G-R(B) at R(B) location - for (int cc = 2 + (FC(rr, 2) & 1); cc < cc1 - 2; cc += 2) { - rix[4] = qix[4] + rr * cc1 + cc; - float v0 = x00625(rix[4][-w1 - 1] + rix[4][-w1 + 1] + rix[4][w1 - 1] + rix[4][w1 + 1]) + x0250(rix[4][0]); - // horizontal - rix[0] = qix[0] + rr * cc1 + cc; - rix[0][0] = - x0250(rix[4][ -2] + rix[4][ 2]) + xdiv2f(rix[4][ -1] + rix[4][0] + rix[4][ 1]); - float Y = v0 + xdiv2f(rix[0][0]); - - if (rix[4][0] > 1.75f * Y) { - rix[0][0] = median(rix[0][0], rix[4][ -1], rix[4][ 1]); - } else { - rix[0][0] = LIM(rix[0][0], 0.0f, 1.0f); - } - - rix[0][0] -= rix[4][0]; - // vertical - rix[1] = qix[1] + rr * cc1 + cc; - rix[1][0] = -x0250(rix[4][-w2] + rix[4][w2]) + xdiv2f(rix[4][-w1] + rix[4][0] + rix[4][w1]); - Y = v0 + xdiv2f(rix[1][0]); - - if (rix[4][0] > 1.75f * Y) { - rix[1][0] = median(rix[1][0], rix[4][-w1], rix[4][w1]); - } else { - rix[1][0] = LIM(rix[1][0], 0.0f, 1.0f); - } - - rix[1][0] -= rix[4][0]; - } - - // G-R(B) at G location - for (int ccc = 2 + (FC(rr, 3) & 1); ccc < cc1 - 2; ccc += 2) { - rix[0] = qix[0] + rr * cc1 + ccc; - rix[1] = qix[1] + rr * cc1 + ccc; - rix[4] = qix[4] + rr * cc1 + ccc; - rix[0][0] = x0250(rix[4][ -2] + rix[4][ 2]) - xdiv2f(rix[4][ -1] + rix[4][0] + rix[4][ 1]); - rix[1][0] = x0250(rix[4][-w2] + rix[4][w2]) - xdiv2f(rix[4][-w1] + rix[4][0] + rix[4][w1]); - rix[0][0] = LIM(rix[0][0], -1.0f, 0.0f) + rix[4][0]; - rix[1][0] = LIM(rix[1][0], -1.0f, 0.0f) + rix[4][0]; - } - } - -#ifdef _OPENMP - #pragma omp single -#endif - { - if (plistener) { - plistener->setProgress (0.2); - } - } - - - // apply low pass filter on differential colors -#ifdef _OPENMP - #pragma omp for -#endif - - for (int rr = 4; rr < rr1 - 4; rr++) - for (int cc = 4; cc < cc1 - 4; cc++) { - rix[0] = qix[0] + rr * cc1 + cc; - rix[2] = qix[2] + rr * cc1 + cc; - rix[2][0] = h0 * rix[0][0] + h1 * (rix[0][ -1] + rix[0][ 1]) + h2 * (rix[0][ -2] + rix[0][ 2]) + h3 * (rix[0][ -3] + rix[0][ 3]) + h4 * (rix[0][ -4] + rix[0][ 4]); - rix[1] = qix[1] + rr * cc1 + cc; - rix[3] = qix[3] + rr * cc1 + cc; - rix[3][0] = h0 * rix[1][0] + h1 * (rix[1][-w1] + rix[1][w1]) + h2 * (rix[1][-w2] + rix[1][w2]) + h3 * (rix[1][-w3] + rix[1][w3]) + h4 * (rix[1][-w4] + rix[1][w4]); - } - -#ifdef _OPENMP - #pragma omp single -#endif - { - if (plistener) { - plistener->setProgress (0.3); - } - } - - // interpolate G-R(B) at R(B) -#ifdef _OPENMP - #pragma omp for -#endif - - for (int rr = 4; rr < rr1 - 4; rr++) { - int cc = 4 + (FC(rr, 4) & 1); -#ifdef __SSE2__ - __m128 p1v, p2v, p3v, p4v, p5v, p6v, p7v, p8v, p9v, muv, vxv, vnv, xhv, vhv, xvv, vvv; - __m128 epsv = _mm_set1_ps(1e-7); - __m128 ninev = _mm_set1_ps(9.f); - - for (; cc < cc1 - 10; cc += 8) { - rix[0] = qix[0] + rr * cc1 + cc; - rix[1] = qix[1] + rr * cc1 + cc; - rix[2] = qix[2] + rr * cc1 + cc; - rix[3] = qix[3] + rr * cc1 + cc; - rix[4] = qix[4] + rr * cc1 + cc; - // horizontal - p1v = LC2VFU(rix[2][-4]); - p2v = LC2VFU(rix[2][-3]); - p3v = LC2VFU(rix[2][-2]); - p4v = LC2VFU(rix[2][-1]); - p5v = LC2VFU(rix[2][ 0]); - p6v = LC2VFU(rix[2][ 1]); - p7v = LC2VFU(rix[2][ 2]); - p8v = LC2VFU(rix[2][ 3]); - p9v = LC2VFU(rix[2][ 4]); - muv = (p1v + p2v + p3v + p4v + p5v + p6v + p7v + p8v + p9v) / ninev; - vxv = epsv + SQRV(p1v - muv) + SQRV(p2v - muv) + SQRV(p3v - muv) + SQRV(p4v - muv) + SQRV(p5v - muv) + SQRV(p6v - muv) + SQRV(p7v - muv) + SQRV(p8v - muv) + SQRV(p9v - muv); - p1v -= LC2VFU(rix[0][-4]); - p2v -= LC2VFU(rix[0][-3]); - p3v -= LC2VFU(rix[0][-2]); - p4v -= LC2VFU(rix[0][-1]); - p5v -= LC2VFU(rix[0][ 0]); - p6v -= LC2VFU(rix[0][ 1]); - p7v -= LC2VFU(rix[0][ 2]); - p8v -= LC2VFU(rix[0][ 3]); - p9v -= LC2VFU(rix[0][ 4]); - vnv = epsv + SQRV(p1v) + SQRV(p2v) + SQRV(p3v) + SQRV(p4v) + SQRV(p5v) + SQRV(p6v) + SQRV(p7v) + SQRV(p8v) + SQRV(p9v); - xhv = (LC2VFU(rix[0][0]) * vxv + LC2VFU(rix[2][0]) * vnv) / (vxv + vnv); - vhv = vxv * vnv / (vxv + vnv); - - // vertical - p1v = LC2VFU(rix[3][-w4]); - p2v = LC2VFU(rix[3][-w3]); - p3v = LC2VFU(rix[3][-w2]); - p4v = LC2VFU(rix[3][-w1]); - p5v = LC2VFU(rix[3][ 0]); - p6v = LC2VFU(rix[3][ w1]); - p7v = LC2VFU(rix[3][ w2]); - p8v = LC2VFU(rix[3][ w3]); - p9v = LC2VFU(rix[3][ w4]); - muv = (p1v + p2v + p3v + p4v + p5v + p6v + p7v + p8v + p9v) / ninev; - vxv = epsv + SQRV(p1v - muv) + SQRV(p2v - muv) + SQRV(p3v - muv) + SQRV(p4v - muv) + SQRV(p5v - muv) + SQRV(p6v - muv) + SQRV(p7v - muv) + SQRV(p8v - muv) + SQRV(p9v - muv); - p1v -= LC2VFU(rix[1][-w4]); - p2v -= LC2VFU(rix[1][-w3]); - p3v -= LC2VFU(rix[1][-w2]); - p4v -= LC2VFU(rix[1][-w1]); - p5v -= LC2VFU(rix[1][ 0]); - p6v -= LC2VFU(rix[1][ w1]); - p7v -= LC2VFU(rix[1][ w2]); - p8v -= LC2VFU(rix[1][ w3]); - p9v -= LC2VFU(rix[1][ w4]); - vnv = epsv + SQRV(p1v) + SQRV(p2v) + SQRV(p3v) + SQRV(p4v) + SQRV(p5v) + SQRV(p6v) + SQRV(p7v) + SQRV(p8v) + SQRV(p9v); - xvv = (LC2VFU(rix[1][0]) * vxv + LC2VFU(rix[3][0]) * vnv) / (vxv + vnv); - vvv = vxv * vnv / (vxv + vnv); - // interpolated G-R(B) - muv = (xhv * vvv + xvv * vhv) / (vhv + vvv); - STC2VFU(rix[4][0], muv); - } - -#endif - - for (; cc < cc1 - 4; cc += 2) { - rix[0] = qix[0] + rr * cc1 + cc; - rix[1] = qix[1] + rr * cc1 + cc; - rix[2] = qix[2] + rr * cc1 + cc; - rix[3] = qix[3] + rr * cc1 + cc; - rix[4] = qix[4] + rr * cc1 + cc; - // horizontal - float p1 = rix[2][-4]; - float p2 = rix[2][-3]; - float p3 = rix[2][-2]; - float p4 = rix[2][-1]; - float p5 = rix[2][ 0]; - float p6 = rix[2][ 1]; - float p7 = rix[2][ 2]; - float p8 = rix[2][ 3]; - float p9 = rix[2][ 4]; - float mu = (p1 + p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9) / 9.f; - float vx = 1e-7 + SQR(p1 - mu) + SQR(p2 - mu) + SQR(p3 - mu) + SQR(p4 - mu) + SQR(p5 - mu) + SQR(p6 - mu) + SQR(p7 - mu) + SQR(p8 - mu) + SQR(p9 - mu); - p1 -= rix[0][-4]; - p2 -= rix[0][-3]; - p3 -= rix[0][-2]; - p4 -= rix[0][-1]; - p5 -= rix[0][ 0]; - p6 -= rix[0][ 1]; - p7 -= rix[0][ 2]; - p8 -= rix[0][ 3]; - p9 -= rix[0][ 4]; - float vn = 1e-7 + SQR(p1) + SQR(p2) + SQR(p3) + SQR(p4) + SQR(p5) + SQR(p6) + SQR(p7) + SQR(p8) + SQR(p9); - float xh = (rix[0][0] * vx + rix[2][0] * vn) / (vx + vn); - float vh = vx * vn / (vx + vn); - - // vertical - p1 = rix[3][-w4]; - p2 = rix[3][-w3]; - p3 = rix[3][-w2]; - p4 = rix[3][-w1]; - p5 = rix[3][ 0]; - p6 = rix[3][ w1]; - p7 = rix[3][ w2]; - p8 = rix[3][ w3]; - p9 = rix[3][ w4]; - mu = (p1 + p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9) / 9.f; - vx = 1e-7 + SQR(p1 - mu) + SQR(p2 - mu) + SQR(p3 - mu) + SQR(p4 - mu) + SQR(p5 - mu) + SQR(p6 - mu) + SQR(p7 - mu) + SQR(p8 - mu) + SQR(p9 - mu); - p1 -= rix[1][-w4]; - p2 -= rix[1][-w3]; - p3 -= rix[1][-w2]; - p4 -= rix[1][-w1]; - p5 -= rix[1][ 0]; - p6 -= rix[1][ w1]; - p7 -= rix[1][ w2]; - p8 -= rix[1][ w3]; - p9 -= rix[1][ w4]; - vn = 1e-7 + SQR(p1) + SQR(p2) + SQR(p3) + SQR(p4) + SQR(p5) + SQR(p6) + SQR(p7) + SQR(p8) + SQR(p9); - float xv = (rix[1][0] * vx + rix[3][0] * vn) / (vx + vn); - float vv = vx * vn / (vx + vn); - // interpolated G-R(B) - rix[4][0] = (xh * vv + xv * vh) / (vh + vv); - } - } - -#ifdef _OPENMP - #pragma omp single -#endif - { - if (plistener) { - plistener->setProgress (0.4); - } - } - - // copy CFA values -#ifdef _OPENMP - #pragma omp for -#endif - - for (int rr = 0; rr < rr1; rr++) - for (int cc = 0, row = rr - ba; cc < cc1; cc++) { - int col = cc - ba; - int c = FC(rr, cc); - rix[c] = qix[c] + rr * cc1 + cc; - - if ((row >= 0) & (row < height) & (col >= 0) & (col < width)) { - rix[c][0] = (*gamtab)[rawData[row][col]]; - } else { - rix[c][0] = 0.f; - } - - if (c != 1) { - rix[1] = qix[1] + rr * cc1 + cc; - rix[4] = qix[4] + rr * cc1 + cc; - rix[1][0] = rix[c][0] + rix[4][0]; - } - } - -#ifdef _OPENMP - #pragma omp single -#endif - { - if (plistener) { - plistener->setProgress (0.5); - } - } - - // bilinear interpolation for R/B - // interpolate R/B at G location -#ifdef _OPENMP - #pragma omp for -#endif - - for (int rr = 1; rr < rr1 - 1; rr++) - for (int cc = 1 + (FC(rr, 2) & 1), c = FC(rr, cc + 1); cc < cc1 - 1; cc += 2) { - rix[c] = qix[c] + rr * cc1 + cc; - rix[1] = qix[1] + rr * cc1 + cc; - rix[c][0] = rix[1][0] + xdiv2f(rix[c][ -1] - rix[1][ -1] + rix[c][ 1] - rix[1][ 1]); - c = 2 - c; - rix[c] = qix[c] + rr * cc1 + cc; - rix[c][0] = rix[1][0] + xdiv2f(rix[c][-w1] - rix[1][-w1] + rix[c][w1] - rix[1][w1]); - c = 2 - c; - } - -#ifdef _OPENMP - #pragma omp single -#endif - { - if (plistener) { - plistener->setProgress (0.6); - } - } - - // interpolate R/B at B/R location -#ifdef _OPENMP - #pragma omp for -#endif - - for (int rr = 1; rr < rr1 - 1; rr++) - for (int cc = 1 + (FC(rr, 1) & 1), c = 2 - FC(rr, cc); cc < cc1 - 1; cc += 2) { - rix[c] = qix[c] + rr * cc1 + cc; - rix[1] = qix[1] + rr * cc1 + cc; - rix[c][0] = rix[1][0] + x0250(rix[c][-w1] - rix[1][-w1] + rix[c][ -1] - rix[1][ -1] + rix[c][ 1] - rix[1][ 1] + rix[c][ w1] - rix[1][ w1]); - } - -#ifdef _OPENMP - #pragma omp single -#endif - { - if (plistener) { - plistener->setProgress (0.7); - } - } - - }// End of parallelization 1 - - // median filter/ - for (int pass = 0; pass < iter; pass++) { - // Apply 3x3 median filter - // Compute median(R-G) and median(B-G) - -#ifdef _OPENMP - #pragma omp parallel for private(rix) -#endif - - for (int rr = 1; rr < rr1 - 1; rr++) { - for (int c = 0; c < 3; c += 2) { - int d = c + 3 - (c == 0 ? 0 : 1); - int cc = 1; -#ifdef __SSE2__ - - for (; cc < cc1 - 4; cc += 4) { - rix[d] = qix[d] + rr * cc1 + cc; - rix[c] = qix[c] + rr * cc1 + cc; - rix[1] = qix[1] + rr * cc1 + cc; - // Assign 3x3 differential color values - const std::array p = { - LVFU(rix[c][-w1 - 1]) - LVFU(rix[1][-w1 - 1]), - LVFU(rix[c][-w1]) - LVFU(rix[1][-w1]), - LVFU(rix[c][-w1 + 1]) - LVFU(rix[1][-w1 + 1]), - LVFU(rix[c][ -1]) - LVFU(rix[1][ -1]), - LVFU(rix[c][ 0]) - LVFU(rix[1][ 0]), - LVFU(rix[c][ 1]) - LVFU(rix[1][ 1]), - LVFU(rix[c][ w1 - 1]) - LVFU(rix[1][ w1 - 1]), - LVFU(rix[c][ w1]) - LVFU(rix[1][ w1]), - LVFU(rix[c][ w1 + 1]) - LVFU(rix[1][ w1 + 1]) - }; - _mm_storeu_ps(&rix[d][0], median(p)); - } - -#endif - - for (; cc < cc1 - 1; cc++) { - rix[d] = qix[d] + rr * cc1 + cc; - rix[c] = qix[c] + rr * cc1 + cc; - rix[1] = qix[1] + rr * cc1 + cc; - // Assign 3x3 differential color values - const std::array p = { - rix[c][-w1 - 1] - rix[1][-w1 - 1], - rix[c][-w1] - rix[1][-w1], - rix[c][-w1 + 1] - rix[1][-w1 + 1], - rix[c][ -1] - rix[1][ -1], - rix[c][ 0] - rix[1][ 0], - rix[c][ 1] - rix[1][ 1], - rix[c][ w1 - 1] - rix[1][ w1 - 1], - rix[c][ w1] - rix[1][ w1], - rix[c][ w1 + 1] - rix[1][ w1 + 1] - }; - rix[d][0] = median(p); - } - } - } - - // red/blue at GREEN pixel locations & red/blue and green at BLUE/RED pixel locations -#ifdef _OPENMP - #pragma omp parallel for private (rix) -#endif - - for (int rr = 0; rr < rr1; rr++) { - rix[0] = qix[0] + rr * cc1; - rix[1] = qix[1] + rr * cc1; - rix[2] = qix[2] + rr * cc1; - rix[3] = qix[3] + rr * cc1; - rix[4] = qix[4] + rr * cc1; - int c0 = FC(rr, 0); - int c1 = FC(rr, 1); - - if(c0 == 1) { - c1 = 2 - c1; - int d = c1 + 3 - (c1 == 0 ? 0 : 1); - int cc; - - for (cc = 0; cc < cc1 - 1; cc += 2) { - rix[0][0] = rix[1][0] + rix[3][0]; - rix[2][0] = rix[1][0] + rix[4][0]; - rix[0]++; - rix[1]++; - rix[2]++; - rix[3]++; - rix[4]++; - rix[c1][0] = rix[1][0] + rix[d][0]; - rix[1][0] = 0.5f * (rix[0][0] - rix[3][0] + rix[2][0] - rix[4][0]); - rix[0]++; - rix[1]++; - rix[2]++; - rix[3]++; - rix[4]++; - } - - if(cc < cc1) { // remaining pixel, only if width is odd - rix[0][0] = rix[1][0] + rix[3][0]; - rix[2][0] = rix[1][0] + rix[4][0]; - } - } else { - c0 = 2 - c0; - int d = c0 + 3 - (c0 == 0 ? 0 : 1); - int cc; - - for (cc = 0; cc < cc1 - 1; cc += 2) { - rix[c0][0] = rix[1][0] + rix[d][0]; - rix[1][0] = 0.5f * (rix[0][0] - rix[3][0] + rix[2][0] - rix[4][0]); - rix[0]++; - rix[1]++; - rix[2]++; - rix[3]++; - rix[4]++; - rix[0][0] = rix[1][0] + rix[3][0]; - rix[2][0] = rix[1][0] + rix[4][0]; - rix[0]++; - rix[1]++; - rix[2]++; - rix[3]++; - rix[4]++; - } - - if(cc < cc1) { // remaining pixel, only if width is odd - rix[c0][0] = rix[1][0] + rix[d][0]; - rix[1][0] = 0.5f * (rix[0][0] - rix[3][0] + rix[2][0] - rix[4][0]); - } - } - } - } - - if (plistener) { - plistener->setProgress (0.8); - } - - if(applyGamma) { - gamtab = &(Color::igammatab_24_17); - } else { - gamtab->makeIdentity(); - } - - array2D* rgb[3]; - rgb[0] = &red; - rgb[1] = &green; - rgb[2] = &blue; - - // copy result back to image matrix -#ifdef _OPENMP - #pragma omp parallel for -#endif - - for (int row = 0; row < height; row++) { - for (int col = 0, rr = row + ba; col < width; col++) { - int cc = col + ba; - int c = FC(row, col); - - for (int ii = 0; ii < 3; ii++) - if (ii != c) { - float *rix = qix[ii] + rr * cc1 + cc; - (*(rgb[ii]))[row][col] = (*gamtab)[65535.f * rix[0]]; - } else { - (*(rgb[ii]))[row][col] = CLIP(rawData[row][col]); - } - } - } - - if (plistener) { - plistener->setProgress (1.0); - } - - if(buffer) { - free(buffer); - } else - for(int i = 0; i < 5; i++) { - free(qix[i]); - } - - if(!applyGamma) { - delete gamtab; - } - - if(iterations > 4 && iterations <= 6) { - refinement(passref); - } else if(iterations > 6) { - refinement_lassus(passref); - } - -} - -/*** -* -* Bayer CFA Demosaicing using Integrated Gaussian Vector on Color Differences -* Revision 1.0 - 2013/02/28 -* -* Copyright (c) 2007-2013 Luis Sanz Rodriguez -* Using High Order Interpolation technique by Jim S, Jimmy Li, and Sharmil Randhawa -* -* Contact info: luis.sanz.rodriguez@gmail.com -* -* This code is distributed under a GNU General Public License, version 3. -* Visit for more information. -* -***/ -// Adapted to RawTherapee by Jacques Desmis 3/2013 -// SSE version by Ingo Weyrich 5/2013 -#ifdef __SSE2__ -#define CLIPV(a) LIMV(a,zerov,c65535v) -void RawImageSource::igv_interpolate(int winw, int winh) -{ - static const float eps = 1e-5f, epssq = 1e-5f; //mod epssq -10f =>-5f Jacques 3/2013 to prevent artifact (divide by zero) - - static const int h1 = 1, h2 = 2, h3 = 3, h5 = 5; - const int width = winw, height = winh; - const int v1 = 1 * width, v2 = 2 * width, v3 = 3 * width, v5 = 5 * width; - float* rgb[2]; - float* chr[4]; - float *rgbarray, *vdif, *hdif, *chrarray; - rgbarray = (float (*)) malloc((width * height) * sizeof( float ) ); - rgb[0] = rgbarray; - rgb[1] = rgbarray + (width * height) / 2; - - vdif = (float (*)) calloc( width * height / 2, sizeof * vdif ); - hdif = (float (*)) calloc( width * height / 2, sizeof * hdif ); - - chrarray = (float (*)) calloc( width * height, sizeof( float ) ); - chr[0] = chrarray; - chr[1] = chrarray + (width * height) / 2; - - // mapped chr[2] and chr[3] to hdif and hdif, because these are out of use, when chr[2] and chr[3] are used - chr[2] = hdif; - chr[3] = vdif; - - border_interpolate2(winw, winh, 7); - - if (plistener) { - plistener->setProgressStr (Glib::ustring::compose(M("TP_RAW_DMETHOD_PROGRESSBAR"), RAWParams::BayerSensor::getMethodString(RAWParams::BayerSensor::Method::IGV))); - plistener->setProgress (0.0); - } - -#ifdef _OPENMP - #pragma omp parallel default(none) shared(rgb,vdif,hdif,chr) -#endif - { - __m128 ngv, egv, wgv, sgv, nvv, evv, wvv, svv, nwgv, negv, swgv, segv, nwvv, nevv, swvv, sevv, tempv, temp1v, temp2v, temp3v, temp4v, temp5v, temp6v, temp7v, temp8v; - __m128 epsv = _mm_set1_ps( eps ); - __m128 epssqv = _mm_set1_ps( epssq ); - __m128 c65535v = _mm_set1_ps( 65535.f ); - __m128 c23v = _mm_set1_ps( 23.f ); - __m128 c40v = _mm_set1_ps( 40.f ); - __m128 c51v = _mm_set1_ps( 51.f ); - __m128 c32v = _mm_set1_ps( 32.f ); - __m128 c8v = _mm_set1_ps( 8.f ); - __m128 c7v = _mm_set1_ps( 7.f ); - __m128 c6v = _mm_set1_ps( 6.f ); - __m128 c10v = _mm_set1_ps( 10.f ); - __m128 c21v = _mm_set1_ps( 21.f ); - __m128 c78v = _mm_set1_ps( 78.f ); - __m128 c69v = _mm_set1_ps( 69.f ); - __m128 c3145680v = _mm_set1_ps( 3145680.f ); - __m128 onev = _mm_set1_ps ( 1.f ); - __m128 zerov = _mm_set1_ps ( 0.f ); - __m128 d725v = _mm_set1_ps ( 0.725f ); - __m128 d1375v = _mm_set1_ps ( 0.1375f ); - - float *dest1, *dest2; - float ng, eg, wg, sg, nv, ev, wv, sv, nwg, neg, swg, seg, nwv, nev, swv, sev; -#ifdef _OPENMP - #pragma omp for -#endif - - for (int row = 0; row < height - 0; row++) { - dest1 = rgb[FC(row, 0) & 1]; - dest2 = rgb[FC(row, 1) & 1]; - int col, indx; - - for (col = 0, indx = row * width + col; col < width - 7; col += 8, indx += 8) { - temp1v = LVFU( rawData[row][col] ); - temp1v = CLIPV( temp1v ); - temp2v = LVFU( rawData[row][col + 4] ); - temp2v = CLIPV( temp2v ); - tempv = _mm_shuffle_ps( temp1v, temp2v, _MM_SHUFFLE( 2, 0, 2, 0 ) ); - _mm_storeu_ps( &dest1[indx >> 1], tempv ); - tempv = _mm_shuffle_ps( temp1v, temp2v, _MM_SHUFFLE( 3, 1, 3, 1 ) ); - _mm_storeu_ps( &dest2[indx >> 1], tempv ); - } - - for (; col < width; col++, indx += 2) { - dest1[indx >> 1] = CLIP(rawData[row][col]); //rawData = RT datas - col++; - if(col < width) - dest2[indx >> 1] = CLIP(rawData[row][col]); //rawData = RT datas - } - } - -#ifdef _OPENMP - #pragma omp single -#endif - { - if (plistener) { - plistener->setProgress (0.13); - } - } - -#ifdef _OPENMP - #pragma omp for -#endif - - for (int row = 5; row < height - 5; row++) { - int col, indx, indx1; - - for (col = 5 + (FC(row, 1) & 1), indx = row * width + col, indx1 = indx >> 1; col < width - 12; col += 8, indx += 8, indx1 += 4) { - //N,E,W,S Gradients - ngv = (epsv + (vabsf(LVFU(rgb[1][(indx - v1) >> 1]) - LVFU(rgb[1][(indx - v3) >> 1])) + vabsf(LVFU(rgb[0][indx1]) - LVFU(rgb[0][(indx1 - v1)]))) / c65535v); - egv = (epsv + (vabsf(LVFU(rgb[1][(indx + h1) >> 1]) - LVFU(rgb[1][(indx + h3) >> 1])) + vabsf(LVFU(rgb[0][indx1]) - LVFU(rgb[0][(indx1 + h1)]))) / c65535v); - wgv = (epsv + (vabsf(LVFU(rgb[1][(indx - h1) >> 1]) - LVFU(rgb[1][(indx - h3) >> 1])) + vabsf(LVFU(rgb[0][indx1]) - LVFU(rgb[0][(indx1 - h1)]))) / c65535v); - sgv = (epsv + (vabsf(LVFU(rgb[1][(indx + v1) >> 1]) - LVFU(rgb[1][(indx + v3) >> 1])) + vabsf(LVFU(rgb[0][indx1]) - LVFU(rgb[0][(indx1 + v1)]))) / c65535v); - //N,E,W,S High Order Interpolation (Li & Randhawa) - //N,E,W,S Hamilton Adams Interpolation - // (48.f * 65535.f) = 3145680.f - tempv = c40v * LVFU(rgb[0][indx1]); - nvv = LIMV(((c23v * LVFU(rgb[1][(indx - v1) >> 1]) + c23v * LVFU(rgb[1][(indx - v3) >> 1]) + LVFU(rgb[1][(indx - v5) >> 1]) + LVFU(rgb[1][(indx + v1) >> 1]) + tempv - c32v * LVFU(rgb[0][(indx1 - v1)]) - c8v * LVFU(rgb[0][(indx1 - v2)]))) / c3145680v, zerov, onev); - evv = LIMV(((c23v * LVFU(rgb[1][(indx + h1) >> 1]) + c23v * LVFU(rgb[1][(indx + h3) >> 1]) + LVFU(rgb[1][(indx + h5) >> 1]) + LVFU(rgb[1][(indx - h1) >> 1]) + tempv - c32v * LVFU(rgb[0][(indx1 + h1)]) - c8v * LVFU(rgb[0][(indx1 + h2)]))) / c3145680v, zerov, onev); - wvv = LIMV(((c23v * LVFU(rgb[1][(indx - h1) >> 1]) + c23v * LVFU(rgb[1][(indx - h3) >> 1]) + LVFU(rgb[1][(indx - h5) >> 1]) + LVFU(rgb[1][(indx + h1) >> 1]) + tempv - c32v * LVFU(rgb[0][(indx1 - h1)]) - c8v * LVFU(rgb[0][(indx1 - h2)]))) / c3145680v, zerov, onev); - svv = LIMV(((c23v * LVFU(rgb[1][(indx + v1) >> 1]) + c23v * LVFU(rgb[1][(indx + v3) >> 1]) + LVFU(rgb[1][(indx + v5) >> 1]) + LVFU(rgb[1][(indx - v1) >> 1]) + tempv - c32v * LVFU(rgb[0][(indx1 + v1)]) - c8v * LVFU(rgb[0][(indx1 + v2)]))) / c3145680v, zerov, onev); - //Horizontal and vertical color differences - tempv = LVFU( rgb[0][indx1] ) / c65535v; - _mm_storeu_ps( &vdif[indx1], (sgv * nvv + ngv * svv) / (ngv + sgv) - tempv ); - _mm_storeu_ps( &hdif[indx1], (wgv * evv + egv * wvv) / (egv + wgv) - tempv ); - } - - // borders without SSE - for (; col < width - 5; col += 2, indx += 2, indx1++) { - //N,E,W,S Gradients - ng = (eps + (fabsf(rgb[1][(indx - v1) >> 1] - rgb[1][(indx - v3) >> 1]) + fabsf(rgb[0][indx1] - rgb[0][(indx1 - v1)])) / 65535.f);; - eg = (eps + (fabsf(rgb[1][(indx + h1) >> 1] - rgb[1][(indx + h3) >> 1]) + fabsf(rgb[0][indx1] - rgb[0][(indx1 + h1)])) / 65535.f); - wg = (eps + (fabsf(rgb[1][(indx - h1) >> 1] - rgb[1][(indx - h3) >> 1]) + fabsf(rgb[0][indx1] - rgb[0][(indx1 - h1)])) / 65535.f); - sg = (eps + (fabsf(rgb[1][(indx + v1) >> 1] - rgb[1][(indx + v3) >> 1]) + fabsf(rgb[0][indx1] - rgb[0][(indx1 + v1)])) / 65535.f); - //N,E,W,S High Order Interpolation (Li & Randhawa) - //N,E,W,S Hamilton Adams Interpolation - // (48.f * 65535.f) = 3145680.f - nv = LIM(((23.0f * rgb[1][(indx - v1) >> 1] + 23.0f * rgb[1][(indx - v3) >> 1] + rgb[1][(indx - v5) >> 1] + rgb[1][(indx + v1) >> 1] + 40.0f * rgb[0][indx1] - 32.0f * rgb[0][(indx1 - v1)] - 8.0f * rgb[0][(indx1 - v2)])) / 3145680.f, 0.0f, 1.0f); - ev = LIM(((23.0f * rgb[1][(indx + h1) >> 1] + 23.0f * rgb[1][(indx + h3) >> 1] + rgb[1][(indx + h5) >> 1] + rgb[1][(indx - h1) >> 1] + 40.0f * rgb[0][indx1] - 32.0f * rgb[0][(indx1 + h1)] - 8.0f * rgb[0][(indx1 + h2)])) / 3145680.f, 0.0f, 1.0f); - wv = LIM(((23.0f * rgb[1][(indx - h1) >> 1] + 23.0f * rgb[1][(indx - h3) >> 1] + rgb[1][(indx - h5) >> 1] + rgb[1][(indx + h1) >> 1] + 40.0f * rgb[0][indx1] - 32.0f * rgb[0][(indx1 - h1)] - 8.0f * rgb[0][(indx1 - h2)])) / 3145680.f, 0.0f, 1.0f); - sv = LIM(((23.0f * rgb[1][(indx + v1) >> 1] + 23.0f * rgb[1][(indx + v3) >> 1] + rgb[1][(indx + v5) >> 1] + rgb[1][(indx - v1) >> 1] + 40.0f * rgb[0][indx1] - 32.0f * rgb[0][(indx1 + v1)] - 8.0f * rgb[0][(indx1 + v2)])) / 3145680.f, 0.0f, 1.0f); - //Horizontal and vertical color differences - vdif[indx1] = (sg * nv + ng * sv) / (ng + sg) - (rgb[0][indx1]) / 65535.f; - hdif[indx1] = (wg * ev + eg * wv) / (eg + wg) - (rgb[0][indx1]) / 65535.f; - } - } - -#ifdef _OPENMP - #pragma omp single -#endif - { - if (plistener) { - plistener->setProgress (0.26); - } - } -#ifdef _OPENMP - #pragma omp for -#endif - - for (int row = 7; row < height - 7; row++) { - int col, d, indx1; - - for (col = 7 + (FC(row, 1) & 1), indx1 = (row * width + col) >> 1, d = FC(row, col) / 2; col < width - 14; col += 8, indx1 += 4) { - //H&V integrated gaussian vector over variance on color differences - //Mod Jacques 3/2013 - ngv = LIMV(epssqv + c78v * SQRV(LVFU(vdif[indx1])) + c69v * (SQRV(LVFU(vdif[indx1 - v1])) + SQRV(LVFU(vdif[indx1 + v1]))) + c51v * (SQRV(LVFU(vdif[indx1 - v2])) + SQRV(LVFU(vdif[indx1 + v2]))) + c21v * (SQRV(LVFU(vdif[indx1 - v3])) + SQRV(LVFU(vdif[indx1 + v3]))) - c6v * SQRV(LVFU(vdif[indx1 - v1]) + LVFU(vdif[indx1]) + LVFU(vdif[indx1 + v1])) - - c10v * (SQRV(LVFU(vdif[indx1 - v2]) + LVFU(vdif[indx1 - v1]) + LVFU(vdif[indx1])) + SQRV(LVFU(vdif[indx1]) + LVFU(vdif[indx1 + v1]) + LVFU(vdif[indx1 + v2]))) - c7v * (SQRV(LVFU(vdif[indx1 - v3]) + LVFU(vdif[indx1 - v2]) + LVFU(vdif[indx1 - v1])) + SQRV(LVFU(vdif[indx1 + v1]) + LVFU(vdif[indx1 + v2]) + LVFU(vdif[indx1 + v3]))), zerov, onev); - egv = LIMV(epssqv + c78v * SQRV(LVFU(hdif[indx1])) + c69v * (SQRV(LVFU(hdif[indx1 - h1])) + SQRV(LVFU(hdif[indx1 + h1]))) + c51v * (SQRV(LVFU(hdif[indx1 - h2])) + SQRV(LVFU(hdif[indx1 + h2]))) + c21v * (SQRV(LVFU(hdif[indx1 - h3])) + SQRV(LVFU(hdif[indx1 + h3]))) - c6v * SQRV(LVFU(hdif[indx1 - h1]) + LVFU(hdif[indx1]) + LVFU(hdif[indx1 + h1])) - - c10v * (SQRV(LVFU(hdif[indx1 - h2]) + LVFU(hdif[indx1 - h1]) + LVFU(hdif[indx1])) + SQRV(LVFU(hdif[indx1]) + LVFU(hdif[indx1 + h1]) + LVFU(hdif[indx1 + h2]))) - c7v * (SQRV(LVFU(hdif[indx1 - h3]) + LVFU(hdif[indx1 - h2]) + LVFU(hdif[indx1 - h1])) + SQRV(LVFU(hdif[indx1 + h1]) + LVFU(hdif[indx1 + h2]) + LVFU(hdif[indx1 + h3]))), zerov, onev); - //Limit chrominance using H/V neighbourhood - nvv = median(d725v * LVFU(vdif[indx1]) + d1375v * LVFU(vdif[indx1 - v1]) + d1375v * LVFU(vdif[indx1 + v1]), LVFU(vdif[indx1 - v1]), LVFU(vdif[indx1 + v1])); - evv = median(d725v * LVFU(hdif[indx1]) + d1375v * LVFU(hdif[indx1 - h1]) + d1375v * LVFU(hdif[indx1 + h1]), LVFU(hdif[indx1 - h1]), LVFU(hdif[indx1 + h1])); - //Chrominance estimation - tempv = (egv * nvv + ngv * evv) / (ngv + egv); - _mm_storeu_ps(&(chr[d][indx1]), tempv); - //Green channel population - temp1v = c65535v * tempv + LVFU(rgb[0][indx1]); - _mm_storeu_ps( &(rgb[0][indx1]), temp1v ); - } - - for (; col < width - 7; col += 2, indx1++) { - //H&V integrated gaussian vector over variance on color differences - //Mod Jacques 3/2013 - ng = LIM(epssq + 78.0f * SQR(vdif[indx1]) + 69.0f * (SQR(vdif[indx1 - v1]) + SQR(vdif[indx1 + v1])) + 51.0f * (SQR(vdif[indx1 - v2]) + SQR(vdif[indx1 + v2])) + 21.0f * (SQR(vdif[indx1 - v3]) + SQR(vdif[indx1 + v3])) - 6.0f * SQR(vdif[indx1 - v1] + vdif[indx1] + vdif[indx1 + v1]) - - 10.0f * (SQR(vdif[indx1 - v2] + vdif[indx1 - v1] + vdif[indx1]) + SQR(vdif[indx1] + vdif[indx1 + v1] + vdif[indx1 + v2])) - 7.0f * (SQR(vdif[indx1 - v3] + vdif[indx1 - v2] + vdif[indx1 - v1]) + SQR(vdif[indx1 + v1] + vdif[indx1 + v2] + vdif[indx1 + v3])), 0.f, 1.f); - eg = LIM(epssq + 78.0f * SQR(hdif[indx1]) + 69.0f * (SQR(hdif[indx1 - h1]) + SQR(hdif[indx1 + h1])) + 51.0f * (SQR(hdif[indx1 - h2]) + SQR(hdif[indx1 + h2])) + 21.0f * (SQR(hdif[indx1 - h3]) + SQR(hdif[indx1 + h3])) - 6.0f * SQR(hdif[indx1 - h1] + hdif[indx1] + hdif[indx1 + h1]) - - 10.0f * (SQR(hdif[indx1 - h2] + hdif[indx1 - h1] + hdif[indx1]) + SQR(hdif[indx1] + hdif[indx1 + h1] + hdif[indx1 + h2])) - 7.0f * (SQR(hdif[indx1 - h3] + hdif[indx1 - h2] + hdif[indx1 - h1]) + SQR(hdif[indx1 + h1] + hdif[indx1 + h2] + hdif[indx1 + h3])), 0.f, 1.f); - //Limit chrominance using H/V neighbourhood - nv = median(0.725f * vdif[indx1] + 0.1375f * vdif[indx1 - v1] + 0.1375f * vdif[indx1 + v1], vdif[indx1 - v1], vdif[indx1 + v1]); - ev = median(0.725f * hdif[indx1] + 0.1375f * hdif[indx1 - h1] + 0.1375f * hdif[indx1 + h1], hdif[indx1 - h1], hdif[indx1 + h1]); - //Chrominance estimation - chr[d][indx1] = (eg * nv + ng * ev) / (ng + eg); - //Green channel population - rgb[0][indx1] = rgb[0][indx1] + 65535.f * chr[d][indx1]; - } - } - -#ifdef _OPENMP - #pragma omp single -#endif - { - if (plistener) { - plistener->setProgress (0.39); - } - } -#ifdef _OPENMP - #pragma omp for -#endif - - for (int row = 7; row < height - 7; row++) { - int col, indx, c; - - for (col = 7 + (FC(row, 1) & 1), indx = row * width + col, c = 1 - FC(row, col) / 2; col < width - 14; col += 8, indx += 8) { - //NW,NE,SW,SE Gradients - nwgv = onev / (epsv + vabsf(LVFU(chr[c][(indx - v1 - h1) >> 1]) - LVFU(chr[c][(indx - v3 - h3) >> 1])) + vabsf(LVFU(chr[c][(indx + v1 + h1) >> 1]) - LVFU(chr[c][(indx - v3 - h3) >> 1]))); - negv = onev / (epsv + vabsf(LVFU(chr[c][(indx - v1 + h1) >> 1]) - LVFU(chr[c][(indx - v3 + h3) >> 1])) + vabsf(LVFU(chr[c][(indx + v1 - h1) >> 1]) - LVFU(chr[c][(indx - v3 + h3) >> 1]))); - swgv = onev / (epsv + vabsf(LVFU(chr[c][(indx + v1 - h1) >> 1]) - LVFU(chr[c][(indx + v3 + h3) >> 1])) + vabsf(LVFU(chr[c][(indx - v1 + h1) >> 1]) - LVFU(chr[c][(indx + v3 - h3) >> 1]))); - segv = onev / (epsv + vabsf(LVFU(chr[c][(indx + v1 + h1) >> 1]) - LVFU(chr[c][(indx + v3 - h3) >> 1])) + vabsf(LVFU(chr[c][(indx - v1 - h1) >> 1]) - LVFU(chr[c][(indx + v3 + h3) >> 1]))); - //Limit NW,NE,SW,SE Color differences - nwvv = median(LVFU(chr[c][(indx - v1 - h1) >> 1]), LVFU(chr[c][(indx - v3 - h1) >> 1]), LVFU(chr[c][(indx - v1 - h3) >> 1])); - nevv = median(LVFU(chr[c][(indx - v1 + h1) >> 1]), LVFU(chr[c][(indx - v3 + h1) >> 1]), LVFU(chr[c][(indx - v1 + h3) >> 1])); - swvv = median(LVFU(chr[c][(indx + v1 - h1) >> 1]), LVFU(chr[c][(indx + v3 - h1) >> 1]), LVFU(chr[c][(indx + v1 - h3) >> 1])); - sevv = median(LVFU(chr[c][(indx + v1 + h1) >> 1]), LVFU(chr[c][(indx + v3 + h1) >> 1]), LVFU(chr[c][(indx + v1 + h3) >> 1])); - //Interpolate chrominance: R@B and B@R - tempv = (nwgv * nwvv + negv * nevv + swgv * swvv + segv * sevv) / (nwgv + negv + swgv + segv); - _mm_storeu_ps( &(chr[c][indx >> 1]), tempv); - } - - for (; col < width - 7; col += 2, indx += 2) { - //NW,NE,SW,SE Gradients - nwg = 1.0f / (eps + fabsf(chr[c][(indx - v1 - h1) >> 1] - chr[c][(indx - v3 - h3) >> 1]) + fabsf(chr[c][(indx + v1 + h1) >> 1] - chr[c][(indx - v3 - h3) >> 1])); - neg = 1.0f / (eps + fabsf(chr[c][(indx - v1 + h1) >> 1] - chr[c][(indx - v3 + h3) >> 1]) + fabsf(chr[c][(indx + v1 - h1) >> 1] - chr[c][(indx - v3 + h3) >> 1])); - swg = 1.0f / (eps + fabsf(chr[c][(indx + v1 - h1) >> 1] - chr[c][(indx + v3 + h3) >> 1]) + fabsf(chr[c][(indx - v1 + h1) >> 1] - chr[c][(indx + v3 - h3) >> 1])); - seg = 1.0f / (eps + fabsf(chr[c][(indx + v1 + h1) >> 1] - chr[c][(indx + v3 - h3) >> 1]) + fabsf(chr[c][(indx - v1 - h1) >> 1] - chr[c][(indx + v3 + h3) >> 1])); - //Limit NW,NE,SW,SE Color differences - nwv = median(chr[c][(indx - v1 - h1) >> 1], chr[c][(indx - v3 - h1) >> 1], chr[c][(indx - v1 - h3) >> 1]); - nev = median(chr[c][(indx - v1 + h1) >> 1], chr[c][(indx - v3 + h1) >> 1], chr[c][(indx - v1 + h3) >> 1]); - swv = median(chr[c][(indx + v1 - h1) >> 1], chr[c][(indx + v3 - h1) >> 1], chr[c][(indx + v1 - h3) >> 1]); - sev = median(chr[c][(indx + v1 + h1) >> 1], chr[c][(indx + v3 + h1) >> 1], chr[c][(indx + v1 + h3) >> 1]); - //Interpolate chrominance: R@B and B@R - chr[c][indx >> 1] = (nwg * nwv + neg * nev + swg * swv + seg * sev) / (nwg + neg + swg + seg); - } - } - -#ifdef _OPENMP - #pragma omp single -#endif - { - if (plistener) { - plistener->setProgress (0.65); - } - } -#ifdef _OPENMP - #pragma omp for -#endif - - for (int row = 7; row < height - 7; row++) { - int col, indx; - - for (col = 7 + (FC(row, 0) & 1), indx = row * width + col; col < width - 14; col += 8, indx += 8) { - //N,E,W,S Gradients - ngv = onev / (epsv + vabsf(LVFU(chr[0][(indx - v1) >> 1]) - LVFU(chr[0][(indx - v3) >> 1])) + vabsf(LVFU(chr[0][(indx + v1) >> 1]) - LVFU(chr[0][(indx - v3) >> 1]))); - egv = onev / (epsv + vabsf(LVFU(chr[0][(indx + h1) >> 1]) - LVFU(chr[0][(indx + h3) >> 1])) + vabsf(LVFU(chr[0][(indx - h1) >> 1]) - LVFU(chr[0][(indx + h3) >> 1]))); - wgv = onev / (epsv + vabsf(LVFU(chr[0][(indx - h1) >> 1]) - LVFU(chr[0][(indx - h3) >> 1])) + vabsf(LVFU(chr[0][(indx + h1) >> 1]) - LVFU(chr[0][(indx - h3) >> 1]))); - sgv = onev / (epsv + vabsf(LVFU(chr[0][(indx + v1) >> 1]) - LVFU(chr[0][(indx + v3) >> 1])) + vabsf(LVFU(chr[0][(indx - v1) >> 1]) - LVFU(chr[0][(indx + v3) >> 1]))); - //Interpolate chrominance: R@G and B@G - tempv = ((ngv * LVFU(chr[0][(indx - v1) >> 1]) + egv * LVFU(chr[0][(indx + h1) >> 1]) + wgv * LVFU(chr[0][(indx - h1) >> 1]) + sgv * LVFU(chr[0][(indx + v1) >> 1])) / (ngv + egv + wgv + sgv)); - _mm_storeu_ps( &chr[0 + 2][indx >> 1], tempv); - } - - for (; col < width - 7; col += 2, indx += 2) { - //N,E,W,S Gradients - ng = 1.0f / (eps + fabsf(chr[0][(indx - v1) >> 1] - chr[0][(indx - v3) >> 1]) + fabsf(chr[0][(indx + v1) >> 1] - chr[0][(indx - v3) >> 1])); - eg = 1.0f / (eps + fabsf(chr[0][(indx + h1) >> 1] - chr[0][(indx + h3) >> 1]) + fabsf(chr[0][(indx - h1) >> 1] - chr[0][(indx + h3) >> 1])); - wg = 1.0f / (eps + fabsf(chr[0][(indx - h1) >> 1] - chr[0][(indx - h3) >> 1]) + fabsf(chr[0][(indx + h1) >> 1] - chr[0][(indx - h3) >> 1])); - sg = 1.0f / (eps + fabsf(chr[0][(indx + v1) >> 1] - chr[0][(indx + v3) >> 1]) + fabsf(chr[0][(indx - v1) >> 1] - chr[0][(indx + v3) >> 1])); - //Interpolate chrominance: R@G and B@G - chr[0 + 2][indx >> 1] = ((ng * chr[0][(indx - v1) >> 1] + eg * chr[0][(indx + h1) >> 1] + wg * chr[0][(indx - h1) >> 1] + sg * chr[0][(indx + v1) >> 1]) / (ng + eg + wg + sg)); - } - } - -#ifdef _OPENMP - #pragma omp single -#endif - { - if (plistener) { - plistener->setProgress (0.78); - } - } -#ifdef _OPENMP - #pragma omp for -#endif - - for (int row = 7; row < height - 7; row++) { - int col, indx; - - for (col = 7 + (FC(row, 0) & 1), indx = row * width + col; col < width - 14; col += 8, indx += 8) { - //N,E,W,S Gradients - ngv = onev / (epsv + vabsf(LVFU(chr[1][(indx - v1) >> 1]) - LVFU(chr[1][(indx - v3) >> 1])) + vabsf(LVFU(chr[1][(indx + v1) >> 1]) - LVFU(chr[1][(indx - v3) >> 1]))); - egv = onev / (epsv + vabsf(LVFU(chr[1][(indx + h1) >> 1]) - LVFU(chr[1][(indx + h3) >> 1])) + vabsf(LVFU(chr[1][(indx - h1) >> 1]) - LVFU(chr[1][(indx + h3) >> 1]))); - wgv = onev / (epsv + vabsf(LVFU(chr[1][(indx - h1) >> 1]) - LVFU(chr[1][(indx - h3) >> 1])) + vabsf(LVFU(chr[1][(indx + h1) >> 1]) - LVFU(chr[1][(indx - h3) >> 1]))); - sgv = onev / (epsv + vabsf(LVFU(chr[1][(indx + v1) >> 1]) - LVFU(chr[1][(indx + v3) >> 1])) + vabsf(LVFU(chr[1][(indx - v1) >> 1]) - LVFU(chr[1][(indx + v3) >> 1]))); - //Interpolate chrominance: R@G and B@G - tempv = ((ngv * LVFU(chr[1][(indx - v1) >> 1]) + egv * LVFU(chr[1][(indx + h1) >> 1]) + wgv * LVFU(chr[1][(indx - h1) >> 1]) + sgv * LVFU(chr[1][(indx + v1) >> 1])) / (ngv + egv + wgv + sgv)); - _mm_storeu_ps( &chr[1 + 2][indx >> 1], tempv); - } - - for (; col < width - 7; col += 2, indx += 2) { - //N,E,W,S Gradients - ng = 1.0f / (eps + fabsf(chr[1][(indx - v1) >> 1] - chr[1][(indx - v3) >> 1]) + fabsf(chr[1][(indx + v1) >> 1] - chr[1][(indx - v3) >> 1])); - eg = 1.0f / (eps + fabsf(chr[1][(indx + h1) >> 1] - chr[1][(indx + h3) >> 1]) + fabsf(chr[1][(indx - h1) >> 1] - chr[1][(indx + h3) >> 1])); - wg = 1.0f / (eps + fabsf(chr[1][(indx - h1) >> 1] - chr[1][(indx - h3) >> 1]) + fabsf(chr[1][(indx + h1) >> 1] - chr[1][(indx - h3) >> 1])); - sg = 1.0f / (eps + fabsf(chr[1][(indx + v1) >> 1] - chr[1][(indx + v3) >> 1]) + fabsf(chr[1][(indx - v1) >> 1] - chr[1][(indx + v3) >> 1])); - //Interpolate chrominance: R@G and B@G - chr[1 + 2][indx >> 1] = ((ng * chr[1][(indx - v1) >> 1] + eg * chr[1][(indx + h1) >> 1] + wg * chr[1][(indx - h1) >> 1] + sg * chr[1][(indx + v1) >> 1]) / (ng + eg + wg + sg)); - } - } - -#ifdef _OPENMP - #pragma omp single -#endif - { - if (plistener) { - plistener->setProgress (0.91); - } - } - float *src1, *src2, *redsrc0, *redsrc1, *bluesrc0, *bluesrc1; -#ifdef _OPENMP - #pragma omp for -#endif - - for(int row = 7; row < height - 7; row++) { - int col, indx, fc; - fc = FC(row, 7) & 1; - src1 = rgb[fc]; - src2 = rgb[fc ^ 1]; - redsrc0 = chr[fc << 1]; - redsrc1 = chr[(fc ^ 1) << 1]; - bluesrc0 = chr[(fc << 1) + 1]; - bluesrc1 = chr[((fc ^ 1) << 1) + 1]; - - for(col = 7, indx = row * width + col; col < width - 14; col += 8, indx += 8) { - temp1v = LVFU( src1[indx >> 1] ); - temp2v = LVFU( src2[(indx + 1) >> 1] ); - tempv = _mm_shuffle_ps( temp1v, temp2v, _MM_SHUFFLE( 1, 0, 1, 0 ) ); - tempv = _mm_shuffle_ps( tempv, tempv, _MM_SHUFFLE( 3, 1, 2, 0 ) ); - _mm_storeu_ps( &green[row][col], CLIPV( tempv )); - temp5v = LVFU(redsrc0[indx >> 1]); - temp6v = LVFU(redsrc1[(indx + 1) >> 1]); - temp3v = _mm_shuffle_ps( temp5v, temp6v, _MM_SHUFFLE( 1, 0, 1, 0 ) ); - temp3v = _mm_shuffle_ps( temp3v, temp3v, _MM_SHUFFLE( 3, 1, 2, 0 ) ); - temp3v = CLIPV( tempv - c65535v * temp3v ); - _mm_storeu_ps( &red[row][col], temp3v); - temp7v = LVFU(bluesrc0[indx >> 1]); - temp8v = LVFU(bluesrc1[(indx + 1) >> 1]); - temp4v = _mm_shuffle_ps( temp7v, temp8v, _MM_SHUFFLE( 1, 0, 1, 0 ) ); - temp4v = _mm_shuffle_ps( temp4v, temp4v, _MM_SHUFFLE( 3, 1, 2, 0 ) ); - temp4v = CLIPV( tempv - c65535v * temp4v ); - _mm_storeu_ps( &blue[row][col], temp4v); - - tempv = _mm_shuffle_ps( temp1v, temp2v, _MM_SHUFFLE( 3, 2, 3, 2 ) ); - tempv = _mm_shuffle_ps( tempv, tempv, _MM_SHUFFLE( 3, 1, 2, 0 ) ); - _mm_storeu_ps( &green[row][col + 4], CLIPV( tempv )); - - temp3v = _mm_shuffle_ps( temp5v, temp6v, _MM_SHUFFLE( 3, 2, 3, 2 ) ); - temp3v = _mm_shuffle_ps( temp3v, temp3v, _MM_SHUFFLE( 3, 1, 2, 0 ) ); - temp3v = CLIPV( tempv - c65535v * temp3v ); - _mm_storeu_ps( &red[row][col + 4], temp3v); - temp4v = _mm_shuffle_ps( temp7v, temp8v, _MM_SHUFFLE( 3, 2, 3, 2 ) ); - temp4v = _mm_shuffle_ps( temp4v, temp4v, _MM_SHUFFLE( 3, 1, 2, 0 ) ); - temp4v = CLIPV( tempv - c65535v * temp4v ); - _mm_storeu_ps( &blue[row][col + 4], temp4v); - } - - for(; col < width - 7; col++, indx += 2) { - red [row][col] = CLIP(src1[indx >> 1] - 65535.f * redsrc0[indx >> 1]); - green[row][col] = CLIP(src1[indx >> 1]); - blue [row][col] = CLIP(src1[indx >> 1] - 65535.f * bluesrc0[indx >> 1]); - col++; - red [row][col] = CLIP(src2[(indx + 1) >> 1] - 65535.f * redsrc1[(indx + 1) >> 1]); - green[row][col] = CLIP(src2[(indx + 1) >> 1]); - blue [row][col] = CLIP(src2[(indx + 1) >> 1] - 65535.f * bluesrc1[(indx + 1) >> 1]); - } - } - }// End of parallelization - - if (plistener) { - plistener->setProgress (1.0); - } - - free(chrarray); - free(rgbarray); - free(vdif); - free(hdif); -} -#undef CLIPV -#else -void RawImageSource::igv_interpolate(int winw, int winh) -{ - static const float eps = 1e-5f, epssq = 1e-5f; //mod epssq -10f =>-5f Jacques 3/2013 to prevent artifact (divide by zero) - static const int h1 = 1, h2 = 2, h3 = 3, h4 = 4, h5 = 5, h6 = 6; - const int width = winw, height = winh; - const int v1 = 1 * width, v2 = 2 * width, v3 = 3 * width, v4 = 4 * width, v5 = 5 * width, v6 = 6 * width; - float* rgb[3]; - float* chr[2]; - float (*rgbarray), *vdif, *hdif, (*chrarray); - - rgbarray = (float (*)) calloc(width * height * 3, sizeof( float)); - rgb[0] = rgbarray; - rgb[1] = rgbarray + (width * height); - rgb[2] = rgbarray + 2 * (width * height); - - chrarray = (float (*)) calloc(width * height * 2, sizeof( float)); - chr[0] = chrarray; - chr[1] = chrarray + (width * height); - - vdif = (float (*)) calloc(width * height / 2, sizeof * vdif); - hdif = (float (*)) calloc(width * height / 2, sizeof * hdif); - - border_interpolate2(winw, winh, 7); - - if (plistener) { - plistener->setProgressStr (Glib::ustring::compose(M("TP_RAW_DMETHOD_PROGRESSBAR"), RAWParams::BayerSensor::getMethodString(RAWParams::BayerSensor::Method::IGV))); - plistener->setProgress (0.0); - } - -#ifdef _OPENMP - #pragma omp parallel default(none) shared(rgb,vdif,hdif,chr) -#endif - { - - float ng, eg, wg, sg, nv, ev, wv, sv, nwg, neg, swg, seg, nwv, nev, swv, sev; - -#ifdef _OPENMP - #pragma omp for -#endif - - for (int row = 0; row < height - 0; row++) - for (int col = 0, indx = row * width + col; col < width - 0; col++, indx++) { - int c = FC(row, col); - rgb[c][indx] = CLIP(rawData[row][col]); //rawData = RT datas - } - -// border_interpolate2(7, rgb); - -#ifdef _OPENMP - #pragma omp single -#endif - { - if (plistener) { - plistener->setProgress (0.13); - } - } - -#ifdef _OPENMP - #pragma omp for -#endif - - for (int row = 5; row < height - 5; row++) - for (int col = 5 + (FC(row, 1) & 1), indx = row * width + col, c = FC(row, col); col < width - 5; col += 2, indx += 2) { - //N,E,W,S Gradients - ng = (eps + (fabsf(rgb[1][indx - v1] - rgb[1][indx - v3]) + fabsf(rgb[c][indx] - rgb[c][indx - v2])) / 65535.f);; - eg = (eps + (fabsf(rgb[1][indx + h1] - rgb[1][indx + h3]) + fabsf(rgb[c][indx] - rgb[c][indx + h2])) / 65535.f); - wg = (eps + (fabsf(rgb[1][indx - h1] - rgb[1][indx - h3]) + fabsf(rgb[c][indx] - rgb[c][indx - h2])) / 65535.f); - sg = (eps + (fabsf(rgb[1][indx + v1] - rgb[1][indx + v3]) + fabsf(rgb[c][indx] - rgb[c][indx + v2])) / 65535.f); - //N,E,W,S High Order Interpolation (Li & Randhawa) - //N,E,W,S Hamilton Adams Interpolation - // (48.f * 65535.f) = 3145680.f - nv = LIM(((23.0f * rgb[1][indx - v1] + 23.0f * rgb[1][indx - v3] + rgb[1][indx - v5] + rgb[1][indx + v1] + 40.0f * rgb[c][indx] - 32.0f * rgb[c][indx - v2] - 8.0f * rgb[c][indx - v4])) / 3145680.f, 0.0f, 1.0f); - ev = LIM(((23.0f * rgb[1][indx + h1] + 23.0f * rgb[1][indx + h3] + rgb[1][indx + h5] + rgb[1][indx - h1] + 40.0f * rgb[c][indx] - 32.0f * rgb[c][indx + h2] - 8.0f * rgb[c][indx + h4])) / 3145680.f, 0.0f, 1.0f); - wv = LIM(((23.0f * rgb[1][indx - h1] + 23.0f * rgb[1][indx - h3] + rgb[1][indx - h5] + rgb[1][indx + h1] + 40.0f * rgb[c][indx] - 32.0f * rgb[c][indx - h2] - 8.0f * rgb[c][indx - h4])) / 3145680.f, 0.0f, 1.0f); - sv = LIM(((23.0f * rgb[1][indx + v1] + 23.0f * rgb[1][indx + v3] + rgb[1][indx + v5] + rgb[1][indx - v1] + 40.0f * rgb[c][indx] - 32.0f * rgb[c][indx + v2] - 8.0f * rgb[c][indx + v4])) / 3145680.f, 0.0f, 1.0f); - //Horizontal and vertical color differences - vdif[indx >> 1] = (sg * nv + ng * sv) / (ng + sg) - (rgb[c][indx]) / 65535.f; - hdif[indx >> 1] = (wg * ev + eg * wv) / (eg + wg) - (rgb[c][indx]) / 65535.f; - } - -#ifdef _OPENMP - #pragma omp single -#endif - { - if (plistener) { - plistener->setProgress (0.26); - } - } - -#ifdef _OPENMP - #pragma omp for -#endif - - for (int row = 7; row < height - 7; row++) - for (int col = 7 + (FC(row, 1) & 1), indx = row * width + col, c = FC(row, col), d = c / 2; col < width - 7; col += 2, indx += 2) { - //H&V integrated gaussian vector over variance on color differences - //Mod Jacques 3/2013 - ng = LIM(epssq + 78.0f * SQR(vdif[indx >> 1]) + 69.0f * (SQR(vdif[(indx - v2) >> 1]) + SQR(vdif[(indx + v2) >> 1])) + 51.0f * (SQR(vdif[(indx - v4) >> 1]) + SQR(vdif[(indx + v4) >> 1])) + 21.0f * (SQR(vdif[(indx - v6) >> 1]) + SQR(vdif[(indx + v6) >> 1])) - 6.0f * SQR(vdif[(indx - v2) >> 1] + vdif[indx >> 1] + vdif[(indx + v2) >> 1]) - - 10.0f * (SQR(vdif[(indx - v4) >> 1] + vdif[(indx - v2) >> 1] + vdif[indx >> 1]) + SQR(vdif[indx >> 1] + vdif[(indx + v2) >> 1] + vdif[(indx + v4) >> 1])) - 7.0f * (SQR(vdif[(indx - v6) >> 1] + vdif[(indx - v4) >> 1] + vdif[(indx - v2) >> 1]) + SQR(vdif[(indx + v2) >> 1] + vdif[(indx + v4) >> 1] + vdif[(indx + v6) >> 1])), 0.f, 1.f); - eg = LIM(epssq + 78.0f * SQR(hdif[indx >> 1]) + 69.0f * (SQR(hdif[(indx - h2) >> 1]) + SQR(hdif[(indx + h2) >> 1])) + 51.0f * (SQR(hdif[(indx - h4) >> 1]) + SQR(hdif[(indx + h4) >> 1])) + 21.0f * (SQR(hdif[(indx - h6) >> 1]) + SQR(hdif[(indx + h6) >> 1])) - 6.0f * SQR(hdif[(indx - h2) >> 1] + hdif[indx >> 1] + hdif[(indx + h2) >> 1]) - - 10.0f * (SQR(hdif[(indx - h4) >> 1] + hdif[(indx - h2) >> 1] + hdif[indx >> 1]) + SQR(hdif[indx >> 1] + hdif[(indx + h2) >> 1] + hdif[(indx + h4) >> 1])) - 7.0f * (SQR(hdif[(indx - h6) >> 1] + hdif[(indx - h4) >> 1] + hdif[(indx - h2) >> 1]) + SQR(hdif[(indx + h2) >> 1] + hdif[(indx + h4) >> 1] + hdif[(indx + h6) >> 1])), 0.f, 1.f); - //Limit chrominance using H/V neighbourhood - nv = median(0.725f * vdif[indx >> 1] + 0.1375f * vdif[(indx - v2) >> 1] + 0.1375f * vdif[(indx + v2) >> 1], vdif[(indx - v2) >> 1], vdif[(indx + v2) >> 1]); - ev = median(0.725f * hdif[indx >> 1] + 0.1375f * hdif[(indx - h2) >> 1] + 0.1375f * hdif[(indx + h2) >> 1], hdif[(indx - h2) >> 1], hdif[(indx + h2) >> 1]); - //Chrominance estimation - chr[d][indx] = (eg * nv + ng * ev) / (ng + eg); - //Green channel population - rgb[1][indx] = rgb[c][indx] + 65535.f * chr[d][indx]; - } - -#ifdef _OPENMP - #pragma omp single -#endif - { - if (plistener) { - plistener->setProgress (0.39); - } - } - -// free(vdif); free(hdif); -#ifdef _OPENMP - #pragma omp for -#endif - - for (int row = 7; row < height - 7; row += 2) - for (int col = 7 + (FC(row, 1) & 1), indx = row * width + col, c = 1 - FC(row, col) / 2; col < width - 7; col += 2, indx += 2) { - //NW,NE,SW,SE Gradients - nwg = 1.0f / (eps + fabsf(chr[c][indx - v1 - h1] - chr[c][indx - v3 - h3]) + fabsf(chr[c][indx + v1 + h1] - chr[c][indx - v3 - h3])); - neg = 1.0f / (eps + fabsf(chr[c][indx - v1 + h1] - chr[c][indx - v3 + h3]) + fabsf(chr[c][indx + v1 - h1] - chr[c][indx - v3 + h3])); - swg = 1.0f / (eps + fabsf(chr[c][indx + v1 - h1] - chr[c][indx + v3 + h3]) + fabsf(chr[c][indx - v1 + h1] - chr[c][indx + v3 - h3])); - seg = 1.0f / (eps + fabsf(chr[c][indx + v1 + h1] - chr[c][indx + v3 - h3]) + fabsf(chr[c][indx - v1 - h1] - chr[c][indx + v3 + h3])); - //Limit NW,NE,SW,SE Color differences - nwv = median(chr[c][indx - v1 - h1], chr[c][indx - v3 - h1], chr[c][indx - v1 - h3]); - nev = median(chr[c][indx - v1 + h1], chr[c][indx - v3 + h1], chr[c][indx - v1 + h3]); - swv = median(chr[c][indx + v1 - h1], chr[c][indx + v3 - h1], chr[c][indx + v1 - h3]); - sev = median(chr[c][indx + v1 + h1], chr[c][indx + v3 + h1], chr[c][indx + v1 + h3]); - //Interpolate chrominance: R@B and B@R - chr[c][indx] = (nwg * nwv + neg * nev + swg * swv + seg * sev) / (nwg + neg + swg + seg); - } - -#ifdef _OPENMP - #pragma omp single -#endif - { - if (plistener) { - plistener->setProgress (0.52); - } - } -#ifdef _OPENMP - #pragma omp for -#endif - - for (int row = 8; row < height - 7; row += 2) - for (int col = 7 + (FC(row, 1) & 1), indx = row * width + col, c = 1 - FC(row, col) / 2; col < width - 7; col += 2, indx += 2) { - //NW,NE,SW,SE Gradients - nwg = 1.0f / (eps + fabsf(chr[c][indx - v1 - h1] - chr[c][indx - v3 - h3]) + fabsf(chr[c][indx + v1 + h1] - chr[c][indx - v3 - h3])); - neg = 1.0f / (eps + fabsf(chr[c][indx - v1 + h1] - chr[c][indx - v3 + h3]) + fabsf(chr[c][indx + v1 - h1] - chr[c][indx - v3 + h3])); - swg = 1.0f / (eps + fabsf(chr[c][indx + v1 - h1] - chr[c][indx + v3 + h3]) + fabsf(chr[c][indx - v1 + h1] - chr[c][indx + v3 - h3])); - seg = 1.0f / (eps + fabsf(chr[c][indx + v1 + h1] - chr[c][indx + v3 - h3]) + fabsf(chr[c][indx - v1 - h1] - chr[c][indx + v3 + h3])); - //Limit NW,NE,SW,SE Color differences - nwv = median(chr[c][indx - v1 - h1], chr[c][indx - v3 - h1], chr[c][indx - v1 - h3]); - nev = median(chr[c][indx - v1 + h1], chr[c][indx - v3 + h1], chr[c][indx - v1 + h3]); - swv = median(chr[c][indx + v1 - h1], chr[c][indx + v3 - h1], chr[c][indx + v1 - h3]); - sev = median(chr[c][indx + v1 + h1], chr[c][indx + v3 + h1], chr[c][indx + v1 + h3]); - //Interpolate chrominance: R@B and B@R - chr[c][indx] = (nwg * nwv + neg * nev + swg * swv + seg * sev) / (nwg + neg + swg + seg); - } - -#ifdef _OPENMP - #pragma omp single -#endif - { - if (plistener) { - plistener->setProgress (0.65); - } - } -#ifdef _OPENMP - #pragma omp for -#endif - - for (int row = 7; row < height - 7; row++) - for (int col = 7 + (FC(row, 0) & 1), indx = row * width + col; col < width - 7; col += 2, indx += 2) { - //N,E,W,S Gradients - ng = 1.0f / (eps + fabsf(chr[0][indx - v1] - chr[0][indx - v3]) + fabsf(chr[0][indx + v1] - chr[0][indx - v3])); - eg = 1.0f / (eps + fabsf(chr[0][indx + h1] - chr[0][indx + h3]) + fabsf(chr[0][indx - h1] - chr[0][indx + h3])); - wg = 1.0f / (eps + fabsf(chr[0][indx - h1] - chr[0][indx - h3]) + fabsf(chr[0][indx + h1] - chr[0][indx - h3])); - sg = 1.0f / (eps + fabsf(chr[0][indx + v1] - chr[0][indx + v3]) + fabsf(chr[0][indx - v1] - chr[0][indx + v3])); - //Interpolate chrominance: R@G and B@G - chr[0][indx] = ((ng * chr[0][indx - v1] + eg * chr[0][indx + h1] + wg * chr[0][indx - h1] + sg * chr[0][indx + v1]) / (ng + eg + wg + sg)); - } - -#ifdef _OPENMP - #pragma omp single -#endif - { - if (plistener) { - plistener->setProgress (0.78); - } - } -#ifdef _OPENMP - #pragma omp for -#endif - - for (int row = 7; row < height - 7; row++) - for (int col = 7 + (FC(row, 0) & 1), indx = row * width + col; col < width - 7; col += 2, indx += 2) { - - //N,E,W,S Gradients - ng = 1.0f / (eps + fabsf(chr[1][indx - v1] - chr[1][indx - v3]) + fabsf(chr[1][indx + v1] - chr[1][indx - v3])); - eg = 1.0f / (eps + fabsf(chr[1][indx + h1] - chr[1][indx + h3]) + fabsf(chr[1][indx - h1] - chr[1][indx + h3])); - wg = 1.0f / (eps + fabsf(chr[1][indx - h1] - chr[1][indx - h3]) + fabsf(chr[1][indx + h1] - chr[1][indx - h3])); - sg = 1.0f / (eps + fabsf(chr[1][indx + v1] - chr[1][indx + v3]) + fabsf(chr[1][indx - v1] - chr[1][indx + v3])); - //Interpolate chrominance: R@G and B@G - chr[1][indx] = ((ng * chr[1][indx - v1] + eg * chr[1][indx + h1] + wg * chr[1][indx - h1] + sg * chr[1][indx + v1]) / (ng + eg + wg + sg)); - } - -#ifdef _OPENMP - #pragma omp single -#endif - { - if (plistener) { - plistener->setProgress (0.91); - } - - //Interpolate borders -// border_interpolate2(7, rgb); - } - /* -#ifdef _OPENMP - #pragma omp for -#endif - for (int row=0; row < height; row++) //borders - for (int col=0; col < width; col++) { - if (col==7 && row >= 7 && row < height-7) - col = width-7; - int indxc=row*width+col; - red [row][col] = rgb[indxc][0]; - green[row][col] = rgb[indxc][1]; - blue [row][col] = rgb[indxc][2]; - } - */ - -#ifdef _OPENMP - #pragma omp for -#endif - - for(int row = 7; row < height - 7; row++) - for(int col = 7, indx = row * width + col; col < width - 7; col++, indx++) { - red [row][col] = CLIP(rgb[1][indx] - 65535.f * chr[0][indx]); - green[row][col] = CLIP(rgb[1][indx]); - blue [row][col] = CLIP(rgb[1][indx] - 65535.f * chr[1][indx]); - } - }// End of parallelization - - if (plistener) { - plistener->setProgress (1.0); - } - - free(chrarray); - free(rgbarray); - free(vdif); - free(hdif); -} -#endif - - -/* - Adaptive Homogeneity-Directed interpolation is based on - the work of Keigo Hirakawa, Thomas Parks, and Paul Lee. - */ -#define TS 256 /* Tile Size */ -#define FORC(cnt) for (c=0; c < cnt; c++) -#define FORC3 FORC(3) - -void RawImageSource::ahd_demosaic() -{ - int i, j, k, top, left, row, col, tr, tc, c, d, val, hm[2]; - float (*pix)[4], (*rix)[3]; - static const int dir[4] = { -1, 1, -TS, TS }; - float ldiff[2][4], abdiff[2][4], leps, abeps; - float xyz[3], xyz_cam[3][4]; - float* cbrt; - float (*rgb)[TS][TS][3]; - float (*lab)[TS][TS][3]; - float (*lix)[3]; - char (*homo)[TS][TS], *buffer; - double r; - - int width = W, height = H; - float (*image)[4]; - unsigned int colors = 3; - - const double xyz_rgb[3][3] = { /* XYZ from RGB */ - { 0.412453, 0.357580, 0.180423 }, - { 0.212671, 0.715160, 0.072169 }, - { 0.019334, 0.119193, 0.950227 } - }; - - const float d65_white[3] = { 0.950456, 1, 1.088754 }; - - if (plistener) { - plistener->setProgressStr (Glib::ustring::compose(M("TP_RAW_DMETHOD_PROGRESSBAR"), RAWParams::BayerSensor::getMethodString(RAWParams::BayerSensor::Method::AHD))); - plistener->setProgress (0.0); - } - - image = (float (*)[4]) calloc (H * W, sizeof * image); - - for (int ii = 0; ii < H; ii++) - for (int jj = 0; jj < W; jj++) { - image[ii * W + jj][fc(ii, jj)] = rawData[ii][jj]; - } - - cbrt = (float (*)) calloc (0x10000, sizeof * cbrt); - - for (i = 0; i < 0x10000; i++) { - r = (double)i / 65535.0; - cbrt[i] = r > 0.008856 ? std::cbrt(r) : 7.787 * r + 16 / 116.0; - } - - for (i = 0; i < 3; i++) - for (unsigned int j = 0; j < colors; j++) - for (xyz_cam[i][j] = k = 0; k < 3; k++) { - xyz_cam[i][j] += xyz_rgb[i][k] * imatrices.rgb_cam[k][j] / d65_white[i]; - } - - border_interpolate(5, image); - buffer = (char *) malloc (13 * TS * TS * sizeof(float)); /* 1664 kB */ - //merror (buffer, "ahd_interpolate()"); - rgb = (float(*)[TS][TS][3]) buffer; - lab = (float(*)[TS][TS][3])(buffer + 6 * TS * TS * sizeof(float)); - homo = (char (*)[TS][TS]) (buffer + 12 * TS * TS * sizeof(float)); - - // helper variables for progress indication - int n_tiles = ((height - 7 + (TS - 7)) / (TS - 6)) * ((width - 7 + (TS - 7)) / (TS - 6)); - int tile = 0; - - for (top = 2; top < height - 5; top += TS - 6) - for (left = 2; left < width - 5; left += TS - 6) { - /* Interpolate green horizontally and vertically: */ - for (row = top; row < top + TS && row < height - 2; row++) { - col = left + (FC(row, left) & 1); - - for (c = FC(row, col); col < left + TS && col < width - 2; col += 2) { - pix = image + (row * width + col); - val = 0.25 * ((pix[-1][1] + pix[0][c] + pix[1][1]) * 2 - - pix[-2][c] - pix[2][c]) ; - rgb[0][row - top][col - left][1] = median(static_cast(val), pix[-1][1], pix[1][1]); - val = 0.25 * ((pix[-width][1] + pix[0][c] + pix[width][1]) * 2 - - pix[-2 * width][c] - pix[2 * width][c]) ; - rgb[1][row - top][col - left][1] = median(static_cast(val), pix[-width][1], pix[width][1]); - } - } - - /* Interpolate red and blue, and convert to CIELab: */ - for (d = 0; d < 2; d++) - for (row = top + 1; row < top + TS - 1 && row < height - 3; row++) - for (col = left + 1; col < left + TS - 1 && col < width - 3; col++) { - pix = image + (row * width + col); - rix = &rgb[d][row - top][col - left]; - lix = &lab[d][row - top][col - left]; - - if ((c = 2 - FC(row, col)) == 1) { - c = FC(row + 1, col); - val = pix[0][1] + (0.5 * ( pix[-1][2 - c] + pix[1][2 - c] - - rix[-1][1] - rix[1][1] ) ); - rix[0][2 - c] = CLIP(val); - val = pix[0][1] + (0.5 * ( pix[-width][c] + pix[width][c] - - rix[-TS][1] - rix[TS][1] ) ); - } else - val = rix[0][1] + (0.25 * ( pix[-width - 1][c] + pix[-width + 1][c] - + pix[+width - 1][c] + pix[+width + 1][c] - - rix[-TS - 1][1] - rix[-TS + 1][1] - - rix[+TS - 1][1] - rix[+TS + 1][1]) ); - - rix[0][c] = CLIP(val); - c = FC(row, col); - rix[0][c] = pix[0][c]; - xyz[0] = xyz[1] = xyz[2] = 0.0; - FORCC { - xyz[0] += xyz_cam[0][c] * rix[0][c]; - xyz[1] += xyz_cam[1][c] * rix[0][c]; - xyz[2] += xyz_cam[2][c] * rix[0][c]; - } - - xyz[0] = CurveFactory::flinterp(cbrt, xyz[0]); - xyz[1] = CurveFactory::flinterp(cbrt, xyz[1]); - xyz[2] = CurveFactory::flinterp(cbrt, xyz[2]); - - //xyz[0] = xyz[0] > 0.008856 ? pow(xyz[0]/65535,1/3.0) : 7.787*xyz[0] + 16/116.0; - //xyz[1] = xyz[1] > 0.008856 ? pow(xyz[1]/65535,1/3.0) : 7.787*xyz[1] + 16/116.0; - //xyz[2] = xyz[2] > 0.008856 ? pow(xyz[2]/65535,1/3.0) : 7.787*xyz[2] + 16/116.0; - - lix[0][0] = (116 * xyz[1] - 16); - lix[0][1] = 500 * (xyz[0] - xyz[1]); - lix[0][2] = 200 * (xyz[1] - xyz[2]); - } - - /* Build homogeneity maps from the CIELab images: */ - memset (homo, 0, 2 * TS * TS); - - for (row = top + 2; row < top + TS - 2 && row < height - 4; row++) { - tr = row - top; - - for (col = left + 2; col < left + TS - 2 && col < width - 4; col++) { - tc = col - left; - - for (d = 0; d < 2; d++) { - lix = &lab[d][tr][tc]; - - for (i = 0; i < 4; i++) { - ldiff[d][i] = ABS(lix[0][0] - lix[dir[i]][0]); - abdiff[d][i] = SQR(lix[0][1] - lix[dir[i]][1]) - + SQR(lix[0][2] - lix[dir[i]][2]); - } - } - - leps = min(max(ldiff[0][0], ldiff[0][1]), - max(ldiff[1][2], ldiff[1][3])); - abeps = min(max(abdiff[0][0], abdiff[0][1]), - max(abdiff[1][2], abdiff[1][3])); - - for (d = 0; d < 2; d++) - for (i = 0; i < 4; i++) - if (ldiff[d][i] <= leps && abdiff[d][i] <= abeps) { - homo[d][tr][tc]++; - } - } - } - - /* Combine the most homogenous pixels for the final result: */ - for (row = top + 3; row < top + TS - 3 && row < height - 5; row++) { - tr = row - top; - - for (col = left + 3; col < left + TS - 3 && col < width - 5; col++) { - tc = col - left; - - for (d = 0; d < 2; d++) - for (hm[d] = 0, i = tr - 1; i <= tr + 1; i++) - for (j = tc - 1; j <= tc + 1; j++) { - hm[d] += homo[d][i][j]; - } - - if (hm[0] != hm[1]) { - FORC3 image[row * width + col][c] = rgb[hm[1] > hm[0]][tr][tc][c]; - } else - FORC3 image[row * width + col][c] = - 0.5 * (rgb[0][tr][tc][c] + rgb[1][tr][tc][c]) ; - } - } - - tile++; - - if(plistener) { - plistener->setProgress((double)tile / n_tiles); - } - } - - if(plistener) { - plistener->setProgress (1.0); - } - - free (buffer); - - for (int i = 0; i < H; i++) { - for (int j = 0; j < W; j++) { - red[i][j] = image[i * W + j][0]; - green[i][j] = image[i * W + j][1]; - blue[i][j] = image[i * W + j][2]; - } - } - - free (image); - free (cbrt); -} -#undef TS - -void RawImageSource::nodemosaic(bool bw) -{ - red(W, H); - green(W, H); - blue(W, H); - #pragma omp parallel for - - for (int i = 0; i < H; i++) { - for (int j = 0; j < W; j++) { - if (bw) { - red[i][j] = green[i][j] = blue[i][j] = rawData[i][j]; - } else if(ri->getSensorType() != ST_FUJI_XTRANS) { - switch( FC(i, j)) { - case 0: - red[i][j] = rawData[i][j]; - green[i][j] = blue[i][j] = 0; - break; - - case 1: - green[i][j] = rawData[i][j]; - red[i][j] = blue[i][j] = 0; - break; - - case 2: - blue[i][j] = rawData[i][j]; - red[i][j] = green[i][j] = 0; - break; - } - } else { - switch( ri->XTRANSFC(i, j)) { - case 0: - red[i][j] = rawData[i][j]; - green[i][j] = blue[i][j] = 0; - break; - - case 1: - green[i][j] = rawData[i][j]; - red[i][j] = blue[i][j] = 0; - break; - - case 2: - blue[i][j] = rawData[i][j]; - red[i][j] = green[i][j] = 0; - break; - } - } - } - } -} - -/* - Refinement based on EECI demosaicing algorithm by L. Chang and Y.P. Tan - Paul Lee - Adapted for RawTherapee - Jacques Desmis 04/2013 -*/ - -#ifdef __SSE2__ -#define CLIPV(a) LIMV(a,ZEROV,c65535v) -#endif -void RawImageSource::refinement(int PassCount) -{ - MyTime t1e, t2e; - t1e.set(); - - int width = W; - int height = H; - int w1 = width; - int w2 = 2 * w1; - - if (plistener) { - plistener->setProgressStr (M("TP_RAW_DMETHOD_PROGRESSBAR_REFINE")); - } - - array2D *rgb[3]; - rgb[0] = &red; - rgb[1] = &green; - rgb[2] = &blue; - - for (int b = 0; b < PassCount; b++) { - if (plistener) { - plistener->setProgress ((float)b / PassCount); - } - - -#ifdef _OPENMP - #pragma omp parallel -#endif - { - float *pix[3]; - - /* Reinforce interpolated green pixels on RED/BLUE pixel locations */ -#ifdef _OPENMP - #pragma omp for -#endif - - for (int row = 2; row < height - 2; row++) { - int col = 2 + (FC(row, 2) & 1); - int c = FC(row, col); -#ifdef __SSE2__ - __m128 dLv, dRv, dUv, dDv, v0v; - __m128 onev = _mm_set1_ps(1.f); - __m128 zd5v = _mm_set1_ps(0.5f); - __m128 c65535v = _mm_set1_ps(65535.f); - - for (; col < width - 8; col += 8) { - int indx = row * width + col; - pix[c] = (float*)(*rgb[c]) + indx; - pix[1] = (float*)(*rgb[1]) + indx; - dLv = onev / (onev + vabsf(LC2VFU(pix[c][ -2]) - LC2VFU(pix[c][0])) + vabsf(LC2VFU(pix[1][ 1]) - LC2VFU(pix[1][ -1]))); - dRv = onev / (onev + vabsf(LC2VFU(pix[c][ 2]) - LC2VFU(pix[c][0])) + vabsf(LC2VFU(pix[1][ 1]) - LC2VFU(pix[1][ -1]))); - dUv = onev / (onev + vabsf(LC2VFU(pix[c][-w2]) - LC2VFU(pix[c][0])) + vabsf(LC2VFU(pix[1][w1]) - LC2VFU(pix[1][-w1]))); - dDv = onev / (onev + vabsf(LC2VFU(pix[c][ w2]) - LC2VFU(pix[c][0])) + vabsf(LC2VFU(pix[1][w1]) - LC2VFU(pix[1][-w1]))); - v0v = CLIPV(LC2VFU(pix[c][0]) + zd5v + ((LC2VFU(pix[1][-1]) - LC2VFU(pix[c][-1])) * dLv + (LC2VFU(pix[1][1]) - LC2VFU(pix[c][1])) * dRv + (LC2VFU(pix[1][-w1]) - LC2VFU(pix[c][-w1])) * dUv + (LC2VFU(pix[1][w1]) - LC2VFU(pix[c][w1])) * dDv ) / (dLv + dRv + dUv + dDv)); - STC2VFU(pix[1][0], v0v); - } - -#endif - - for (; col < width - 2; col += 2) { - int indx = row * width + col; - pix[c] = (float*)(*rgb[c]) + indx; - pix[1] = (float*)(*rgb[1]) + indx; - float dL = 1.f / (1.f + fabsf(pix[c][ -2] - pix[c][0]) + fabsf(pix[1][ 1] - pix[1][ -1])); - float dR = 1.f / (1.f + fabsf(pix[c][ 2] - pix[c][0]) + fabsf(pix[1][ 1] - pix[1][ -1])); - float dU = 1.f / (1.f + fabsf(pix[c][-w2] - pix[c][0]) + fabsf(pix[1][w1] - pix[1][-w1])); - float dD = 1.f / (1.f + fabsf(pix[c][ w2] - pix[c][0]) + fabsf(pix[1][w1] - pix[1][-w1])); - float v0 = (pix[c][0] + 0.5f + ((pix[1][ -1] - pix[c][ -1]) * dL + (pix[1][ 1] - pix[c][ 1]) * dR + (pix[1][-w1] - pix[c][-w1]) * dU + (pix[1][ w1] - pix[c][ w1]) * dD ) / (dL + dR + dU + dD)); - pix[1][0] = CLIP(v0); - } - } - - /* Reinforce interpolated red/blue pixels on GREEN pixel locations */ -#ifdef _OPENMP - #pragma omp for -#endif - - for (int row = 2; row < height - 2; row++) { - int col = 2 + (FC(row, 3) & 1); - int c = FC(row, col + 1); -#ifdef __SSE2__ - __m128 dLv, dRv, dUv, dDv, v0v; - __m128 onev = _mm_set1_ps(1.f); - __m128 zd5v = _mm_set1_ps(0.5f); - __m128 c65535v = _mm_set1_ps(65535.f); - - for (; col < width - 8; col += 8) { - int indx = row * width + col; - pix[1] = (float*)(*rgb[1]) + indx; - - for (int i = 0; i < 2; c = 2 - c, i++) { - pix[c] = (float*)(*rgb[c]) + indx; - dLv = onev / (onev + vabsf(LC2VFU(pix[1][ -2]) - LC2VFU(pix[1][0])) + vabsf(LC2VFU(pix[c][ 1]) - LC2VFU(pix[c][ -1]))); - dRv = onev / (onev + vabsf(LC2VFU(pix[1][ 2]) - LC2VFU(pix[1][0])) + vabsf(LC2VFU(pix[c][ 1]) - LC2VFU(pix[c][ -1]))); - dUv = onev / (onev + vabsf(LC2VFU(pix[1][-w2]) - LC2VFU(pix[1][0])) + vabsf(LC2VFU(pix[c][w1]) - LC2VFU(pix[c][-w1]))); - dDv = onev / (onev + vabsf(LC2VFU(pix[1][ w2]) - LC2VFU(pix[1][0])) + vabsf(LC2VFU(pix[c][w1]) - LC2VFU(pix[c][-w1]))); - v0v = CLIPV(LC2VFU(pix[1][0]) + zd5v - ((LC2VFU(pix[1][-1]) - LC2VFU(pix[c][-1])) * dLv + (LC2VFU(pix[1][1]) - LC2VFU(pix[c][1])) * dRv + (LC2VFU(pix[1][-w1]) - LC2VFU(pix[c][-w1])) * dUv + (LC2VFU(pix[1][w1]) - LC2VFU(pix[c][w1])) * dDv ) / (dLv + dRv + dUv + dDv)); - STC2VFU(pix[c][0], v0v); - } - } - -#endif - - for (; col < width - 2; col += 2) { - int indx = row * width + col; - pix[1] = (float*)(*rgb[1]) + indx; - - for (int i = 0; i < 2; c = 2 - c, i++) { - pix[c] = (float*)(*rgb[c]) + indx; - float dL = 1.f / (1.f + fabsf(pix[1][ -2] - pix[1][0]) + fabsf(pix[c][ 1] - pix[c][ -1])); - float dR = 1.f / (1.f + fabsf(pix[1][ 2] - pix[1][0]) + fabsf(pix[c][ 1] - pix[c][ -1])); - float dU = 1.f / (1.f + fabsf(pix[1][-w2] - pix[1][0]) + fabsf(pix[c][w1] - pix[c][-w1])); - float dD = 1.f / (1.f + fabsf(pix[1][ w2] - pix[1][0]) + fabsf(pix[c][w1] - pix[c][-w1])); - float v0 = (pix[1][0] + 0.5f - ((pix[1][ -1] - pix[c][ -1]) * dL + (pix[1][ 1] - pix[c][ 1]) * dR + (pix[1][-w1] - pix[c][-w1]) * dU + (pix[1][ w1] - pix[c][ w1]) * dD ) / (dL + dR + dU + dD)); - pix[c][0] = CLIP(v0); - } - } - } - - /* Reinforce integrated red/blue pixels on BLUE/RED pixel locations */ -#ifdef _OPENMP - #pragma omp for -#endif - - for (int row = 2; row < height - 2; row++) { - int col = 2 + (FC(row, 2) & 1); - int c = 2 - FC(row, col); -#ifdef __SSE2__ - __m128 dLv, dRv, dUv, dDv, v0v; - __m128 onev = _mm_set1_ps(1.f); - __m128 zd5v = _mm_set1_ps(0.5f); - __m128 c65535v = _mm_set1_ps(65535.f); - - for (; col < width - 8; col += 8) { - int indx = row * width + col; - pix[0] = (float*)(*rgb[0]) + indx; - pix[1] = (float*)(*rgb[1]) + indx; - pix[2] = (float*)(*rgb[2]) + indx; - int d = 2 - c; - dLv = onev / (onev + vabsf(LC2VFU(pix[d][ -2]) - LC2VFU(pix[d][0])) + vabsf(LC2VFU(pix[1][ 1]) - LC2VFU(pix[1][ -1]))); - dRv = onev / (onev + vabsf(LC2VFU(pix[d][ 2]) - LC2VFU(pix[d][0])) + vabsf(LC2VFU(pix[1][ 1]) - LC2VFU(pix[1][ -1]))); - dUv = onev / (onev + vabsf(LC2VFU(pix[d][-w2]) - LC2VFU(pix[d][0])) + vabsf(LC2VFU(pix[1][w1]) - LC2VFU(pix[1][-w1]))); - dDv = onev / (onev + vabsf(LC2VFU(pix[d][ w2]) - LC2VFU(pix[d][0])) + vabsf(LC2VFU(pix[1][w1]) - LC2VFU(pix[1][-w1]))); - v0v = CLIPV(LC2VFU(pix[1][0]) + zd5v - ((LC2VFU(pix[1][-1]) - LC2VFU(pix[c][-1])) * dLv + (LC2VFU(pix[1][1]) - LC2VFU(pix[c][1])) * dRv + (LC2VFU(pix[1][-w1]) - LC2VFU(pix[c][-w1])) * dUv + (LC2VFU(pix[1][w1]) - LC2VFU(pix[c][w1])) * dDv ) / (dLv + dRv + dUv + dDv)); - STC2VFU(pix[c][0], v0v); - } - -#endif - - for (; col < width - 2; col += 2) { - int indx = row * width + col; - pix[0] = (float*)(*rgb[0]) + indx; - pix[1] = (float*)(*rgb[1]) + indx; - pix[2] = (float*)(*rgb[2]) + indx; - int d = 2 - c; - float dL = 1.f / (1.f + fabsf(pix[d][ -2] - pix[d][0]) + fabsf(pix[1][ 1] - pix[1][ -1])); - float dR = 1.f / (1.f + fabsf(pix[d][ 2] - pix[d][0]) + fabsf(pix[1][ 1] - pix[1][ -1])); - float dU = 1.f / (1.f + fabsf(pix[d][-w2] - pix[d][0]) + fabsf(pix[1][w1] - pix[1][-w1])); - float dD = 1.f / (1.f + fabsf(pix[d][ w2] - pix[d][0]) + fabsf(pix[1][w1] - pix[1][-w1])); - float v0 = (pix[1][0] + 0.5f - ((pix[1][ -1] - pix[c][ -1]) * dL + (pix[1][ 1] - pix[c][ 1]) * dR + (pix[1][-w1] - pix[c][-w1]) * dU + (pix[1][ w1] - pix[c][ w1]) * dD ) / (dL + dR + dU + dD)); - pix[c][0] = CLIP(v0); - } - } - } // end parallel - } - - t2e.set(); - - if (settings->verbose) { - printf("Refinement Lee %d usec\n", t2e.etime(t1e)); - } -} -#ifdef __SSE2__ -#undef CLIPV -#endif - - -// Refinement based on EECI demozaicing algorithm by L. Chang and Y.P. Tan -// from "Lassus" : Luis Sanz Rodriguez, adapted by Jacques Desmis - JDC - and Oliver Duis for RawTherapee -// increases the signal to noise ratio (PSNR) # +1 to +2 dB : tested with Dcraw : eg: Lighthouse + AMaZE : whitout refinement:39.96dB, with refinement:41.86 dB -// reduce color artifacts, improves the interpolation -// but it's relatively slow -// -// Should be DISABLED if it decreases image quality by increases some image noise and generates blocky edges -void RawImageSource::refinement_lassus(int PassCount) -{ - // const int PassCount=1; - - // if (settings->verbose) printf("Refinement\n"); - - MyTime t1e, t2e; - t1e.set(); - int u = W, v = 2 * u, w = 3 * u, x = 4 * u, y = 5 * u; - float (*image)[3]; - image = (float(*)[3]) calloc(W * H, sizeof * image); -#ifdef _OPENMP - #pragma omp parallel shared(image) -#endif - { - // convert red, blue, green to image -#ifdef _OPENMP - #pragma omp for -#endif - - for (int i = 0; i < H; i++) { - for (int j = 0; j < W; j++) { - image[i * W + j][0] = red [i][j]; - image[i * W + j][1] = green[i][j]; - image[i * W + j][2] = blue [i][j]; - } - } - - for (int b = 0; b < PassCount; b++) { - if (plistener) { - plistener->setProgressStr (M("TP_RAW_DMETHOD_PROGRESSBAR_REFINE")); - plistener->setProgress ((float)b / PassCount); - } - - // Reinforce interpolated green pixels on RED/BLUE pixel locations -#ifdef _OPENMP - #pragma omp for -#endif - - for (int row = 6; row < H - 6; row++) { - for (int col = 6 + (FC(row, 2) & 1), c = FC(row, col); col < W - 6; col += 2) { - float (*pix)[3] = image + row * W + col; - - // Cubic Spline Interpolation by Li and Randhawa, modified by Luis Sanz Rodriguez - - float f[4]; - f[0] = 1.0f / (1.0f + xmul2f(fabs(x1125(pix[-v][c]) - x0875(pix[0][c]) - x0250(pix[-x][c]))) + fabs(x0875(pix[u][1]) - x1125(pix[-u][1]) + x0250(pix[-w][1])) + fabs(x0875(pix[-w][1]) - x1125(pix[-u][1]) + x0250(pix[-y][1]))); - f[1] = 1.0f / (1.0f + xmul2f(fabs(x1125(pix[+2][c]) - x0875(pix[0][c]) - x0250(pix[+4][c]))) + fabs(x0875(pix[1][1]) - x1125(pix[-1][1]) + x0250(pix[+3][1])) + fabs(x0875(pix[+3][1]) - x1125(pix[+1][1]) + x0250(pix[+5][1]))); - f[2] = 1.0f / (1.0f + xmul2f(fabs(x1125(pix[-2][c]) - x0875(pix[0][c]) - x0250(pix[-4][c]))) + fabs(x0875(pix[1][1]) - x1125(pix[-1][1]) + x0250(pix[-3][1])) + fabs(x0875(pix[-3][1]) - x1125(pix[-1][1]) + x0250(pix[-5][1]))); - f[3] = 1.0f / (1.0f + xmul2f(fabs(x1125(pix[+v][c]) - x0875(pix[0][c]) - x0250(pix[+x][c]))) + fabs(x0875(pix[u][1]) - x1125(pix[-u][1]) + x0250(pix[+w][1])) + fabs(x0875(pix[+w][1]) - x1125(pix[+u][1]) + x0250(pix[+y][1]))); - - float g[4];//CLIREF avoid overflow - g[0] = pix[0][c] + (x0875(CLIREF(pix[-u][1] - pix[-u][c])) + x0125(CLIREF(pix[+u][1] - pix[+u][c]))); - g[1] = pix[0][c] + (x0875(CLIREF(pix[+1][1] - pix[+1][c])) + x0125(CLIREF(pix[-1][1] - pix[-1][c]))); - g[2] = pix[0][c] + (x0875(CLIREF(pix[-1][1] - pix[-1][c])) + x0125(CLIREF(pix[+1][1] - pix[+1][c]))); - g[3] = pix[0][c] + (x0875(CLIREF(pix[+u][1] - pix[+u][c])) + x0125(CLIREF(pix[-u][1] - pix[-u][c]))); - - pix[0][1] = (f[0] * g[0] + f[1] * g[1] + f[2] * g[2] + f[3] * g[3]) / (f[0] + f[1] + f[2] + f[3]); - - } - } - - // Reinforce interpolated red/blue pixels on GREEN pixel locations -#ifdef _OPENMP - #pragma omp for -#endif - - for (int row = 6; row < H - 6; row++) { - for (int col = 6 + (FC(row, 3) & 1), c = FC(row, col + 1); col < W - 6; col += 2) { - float (*pix)[3] = image + row * W + col; - - for (int i = 0; i < 2; c = 2 - c, i++) { - float f[4]; - f[0] = 1.0f / (1.0f + xmul2f(fabs(x0875(pix[-v][1]) - x1125(pix[0][1]) + x0250(pix[-x][1]))) + fabs(pix[u] [c] - pix[-u][c]) + fabs(pix[-w][c] - pix[-u][c])); - f[1] = 1.0f / (1.0f + xmul2f(fabs(x0875(pix[+2][1]) - x1125(pix[0][1]) + x0250(pix[+4][1]))) + fabs(pix[+1][c] - pix[-1][c]) + fabs(pix[+3][c] - pix[+1][c])); - f[2] = 1.0f / (1.0f + xmul2f(fabs(x0875(pix[-2][1]) - x1125(pix[0][1]) + x0250(pix[-4][1]))) + fabs(pix[+1][c] - pix[-1][c]) + fabs(pix[-3][c] - pix[-1][c])); - f[3] = 1.0f / (1.0f + xmul2f(fabs(x0875(pix[+v][1]) - x1125(pix[0][1]) + x0250(pix[+x][1]))) + fabs(pix[u] [c] - pix[-u][c]) + fabs(pix[+w][c] - pix[+u][c])); - - float g[5];//CLIREF avoid overflow - g[0] = CLIREF(pix[-u][1] - pix[-u][c]); - g[1] = CLIREF(pix[+1][1] - pix[+1][c]); - g[2] = CLIREF(pix[-1][1] - pix[-1][c]); - g[3] = CLIREF(pix[+u][1] - pix[+u][c]); - g[4] = ((f[0] * g[0] + f[1] * g[1] + f[2] * g[2] + f[3] * g[3]) / (f[0] + f[1] + f[2] + f[3])); - pix[0][c] = pix[0][1] - (0.65f * g[4] + 0.35f * CLIREF(pix[0][1] - pix[0][c])); - } - } - } - - // Reinforce integrated red/blue pixels on BLUE/RED pixel locations -#ifdef _OPENMP - #pragma omp for -#endif - - for (int row = 6; row < H - 6; row++) { - for (int col = 6 + (FC(row, 2) & 1), c = 2 - FC(row, col), d = 2 - c; col < W - 6; col += 2) { - float (*pix)[3] = image + row * W + col; - - float f[4]; - f[0] = 1.0f / (1.0f + xmul2f(fabs(x1125(pix[-v][d]) - x0875(pix[0][d]) - x0250(pix[-x][d]))) + fabs(x0875(pix[u][1]) - x1125(pix[-u][1]) + x0250(pix[-w][1])) + fabs(x0875(pix[-w][1]) - x1125(pix[-u][1]) + x0250(pix[-y][1]))); - f[1] = 1.0f / (1.0f + xmul2f(fabs(x1125(pix[+2][d]) - x0875(pix[0][d]) - x0250(pix[+4][d]))) + fabs(x0875(pix[1][1]) - x1125(pix[-1][1]) + x0250(pix[+3][1])) + fabs(x0875(pix[+3][1]) - x1125(pix[+1][1]) + x0250(pix[+5][1]))); - f[2] = 1.0f / (1.0f + xmul2f(fabs(x1125(pix[-2][d]) - x0875(pix[0][d]) - x0250(pix[-4][d]))) + fabs(x0875(pix[1][1]) - x1125(pix[-1][1]) + x0250(pix[-3][1])) + fabs(x0875(pix[-3][1]) - x1125(pix[-1][1]) + x0250(pix[-5][1]))); - f[3] = 1.0f / (1.0f + xmul2f(fabs(x1125(pix[+v][d]) - x0875(pix[0][d]) - x0250(pix[+x][d]))) + fabs(x0875(pix[u][1]) - x1125(pix[-u][1]) + x0250(pix[+w][1])) + fabs(x0875(pix[+w][1]) - x1125(pix[+u][1]) + x0250(pix[+y][1]))); - - float g[5]; - g[0] = (x0875((pix[-u][1] - pix[-u][c])) + x0125((pix[-v][1] - pix[-v][c]))); - g[1] = (x0875((pix[+1][1] - pix[+1][c])) + x0125((pix[+2][1] - pix[+2][c]))); - g[2] = (x0875((pix[-1][1] - pix[-1][c])) + x0125((pix[-2][1] - pix[-2][c]))); - g[3] = (x0875((pix[+u][1] - pix[+u][c])) + x0125((pix[+v][1] - pix[+v][c]))); - - g[4] = (f[0] * g[0] + f[1] * g[1] + f[2] * g[2] + f[3] * g[3]) / (f[0] + f[1] + f[2] + f[3]); - - const std::array p = { - pix[-u - 1][1] - pix[-u - 1][c], - pix[-u + 0][1] - pix[-u + 0][c], - pix[-u + 1][1] - pix[-u + 1][c], - pix[+0 - 1][1] - pix[+0 - 1][c], - pix[+0 + 0][1] - pix[+0 + 0][c], - pix[+0 + 1][1] - pix[+0 + 1][c], - pix[+u - 1][1] - pix[+u - 1][c], - pix[+u + 0][1] - pix[+u + 0][c], - pix[+u + 1][1] - pix[+u + 1][c] - }; - - const float med = median(p); - - pix[0][c] = LIM(pix[0][1] - (1.30f * g[4] - 0.30f * (pix[0][1] - pix[0][c])), 0.99f * (pix[0][1] - med), 1.01f * (pix[0][1] - med)); - - } - } - - } - - // put modified values to red, green, blue -#ifdef _OPENMP - #pragma omp for -#endif - - for (int i = 0; i < H; i++) { - for (int j = 0; j < W; j++) { - red [i][j] = image[i * W + j][0]; - green[i][j] = image[i * W + j][1]; - blue [i][j] = image[i * W + j][2]; - } - } - } - - free(image); - - t2e.set(); - - if (settings->verbose) { - printf("Refinement Lassus %d usec\n", t2e.etime(t1e)); - } -} - - -/* - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of the author nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -// If you want to use the code, you need to display name of the original authors in -// your software! - -/* DCB demosaicing by Jacek Gozdz (cuniek@kft.umcs.lublin.pl) - * the code is open source (BSD licence) -*/ - -#define TILESIZE 192 -#define TILEBORDER 10 -#define CACHESIZE (TILESIZE+2*TILEBORDER) - -inline void RawImageSource::dcb_initTileLimits(int &colMin, int &rowMin, int &colMax, int &rowMax, int x0, int y0, int border) -{ - rowMin = border; - colMin = border; - rowMax = CACHESIZE - border; - colMax = CACHESIZE - border; - - if(!y0 ) { - rowMin = TILEBORDER + border; - } - - if(!x0 ) { - colMin = TILEBORDER + border; - } - - if( y0 + TILESIZE + TILEBORDER >= H - border) { - rowMax = TILEBORDER + H - border - y0; - } - - if( x0 + TILESIZE + TILEBORDER >= W - border) { - colMax = TILEBORDER + W - border - x0; - } -} - -void RawImageSource::fill_raw( float (*cache )[3], int x0, int y0, float** rawData) -{ - int rowMin, colMin, rowMax, colMax; - dcb_initTileLimits(colMin, rowMin, colMax, rowMax, x0, y0, 0); - - for (int row = rowMin, y = y0 - TILEBORDER + rowMin; row < rowMax; row++, y++) - for (int col = colMin, x = x0 - TILEBORDER + colMin, indx = row * CACHESIZE + col; col < colMax; col++, x++, indx++) { - cache[indx][fc(y, x)] = rawData[y][x]; - } -} - -void RawImageSource::fill_border( float (*cache )[3], int border, int x0, int y0) -{ - unsigned f; - float sum[8]; - constexpr unsigned int colors = 3; // used in FORCC - - for (int row = y0; row < y0 + TILESIZE + TILEBORDER && row < H; row++) { - for (int col = x0; col < x0 + TILESIZE + TILEBORDER && col < W; col++) { - if (col >= border && col < W - border && row >= border && row < H - border) { - col = W - border; - - if(col >= x0 + TILESIZE + TILEBORDER ) { - break; - } - } - - memset(sum, 0, sizeof sum); - - for (int y = row - 1; y != row + 2; y++) - for (int x = col - 1; x != col + 2; x++) - if (y < H && y < y0 + TILESIZE + TILEBORDER && x < W && x < x0 + TILESIZE + TILEBORDER) { - f = fc(y, x); - sum[f] += cache[(y - y0 + TILEBORDER) * CACHESIZE + TILEBORDER + x - x0][f]; - sum[f + 4]++; - } - - f = fc(row, col); - FORCC - - if (c != f && sum[c + 4] > 0) { - cache[(row - y0 + TILEBORDER) * CACHESIZE + TILEBORDER + col - x0][c] = sum[c] / sum[c + 4]; - } - } - } -} - -// saves red and blue - -// change buffer[3] -> buffer[2], possibly to buffer[1] if split -// into two loops, one for R and another for B, could also be smaller because -// there is no need for green pixels pass -// this would decrease the amount of needed memory -// from megapixels*2 records to megapixels*0.5 -// also don't know if float is needed as data is 1-65536 integer (I believe!!) -// comment from Ingo: float is needed because rawdata in rt is float -void RawImageSource::copy_to_buffer( float (*buffer)[2], float (*image)[3]) -{ - for (int indx = 0; indx < CACHESIZE * CACHESIZE; indx++) { - buffer[indx][0] = image[indx][0]; //R - buffer[indx][1] = image[indx][2]; //B - } -} - -// restores red and blue - -// other comments like in copy_to_buffer -void RawImageSource::restore_from_buffer(float (*image)[3], float (*buffer)[2]) -{ - for (int indx = 0; indx < CACHESIZE * CACHESIZE; indx++) { - image[indx][0] = buffer[indx][0]; //R - image[indx][2] = buffer[indx][1]; //B - } -} - -// First pass green interpolation - -// remove entirely: bufferH and bufferV -void RawImageSource::dcb_hid(float (*image)[3], int x0, int y0) -{ - const int u = CACHESIZE; - int rowMin, colMin, rowMax, colMax; - dcb_initTileLimits(colMin, rowMin, colMax, rowMax, x0, y0, 2); - -// simple green bilinear in R and B pixels - for (int row = rowMin; row < rowMax; row++) - for (int col = colMin + (FC(y0 - TILEBORDER + row, x0 - TILEBORDER + colMin) & 1), indx = row * CACHESIZE + col; col < colMax; col += 2, indx += 2) { - assert(indx - u - 1 >= 0 && indx + u + 1 < u * u); - - image[indx][1] = 0.25*(image[indx-1][1]+image[indx+1][1]+image[indx-u][1]+image[indx+u][1]); - } -} - -// missing colours are interpolated -void RawImageSource::dcb_color(float (*image)[3], int x0, int y0) -{ - const int u = CACHESIZE; - int rowMin, colMin, rowMax, colMax; - dcb_initTileLimits(colMin, rowMin, colMax, rowMax, x0, y0, 1); - - // red in blue pixel, blue in red pixel - for (int row = rowMin; row < rowMax; row++) - for (int col = colMin + (FC(y0 - TILEBORDER + row, x0 - TILEBORDER + colMin) & 1), indx = row * CACHESIZE + col, c = 2 - FC(y0 - TILEBORDER + row, x0 - TILEBORDER + col); col < colMax; col += 2, indx += 2) { - assert(indx >= 0 && indx < u * u && c >= 0 && c < 4); - - -//Jacek comment: one multiplication less - image[indx][c] = image[indx][1] + - ( image[indx + u + 1][c] + image[indx + u - 1][c] + image[indx - u + 1][c] + image[indx - u - 1][c] - - (image[indx + u + 1][1] + image[indx + u - 1][1] + image[indx - u + 1][1] + image[indx - u - 1][1]) ) * 0.25f; - -/* original - image[indx][c] = ( 4.f * image[indx][1] - - image[indx + u + 1][1] - image[indx + u - 1][1] - image[indx - u + 1][1] - image[indx - u - 1][1] - + image[indx + u + 1][c] + image[indx + u - 1][c] + image[indx - u + 1][c] + image[indx - u - 1][c] ) * 0.25f; -*/ - } - - // red or blue in green pixels - for (int row = rowMin; row < rowMax; row++) - for (int col = colMin + (FC(y0 - TILEBORDER + row, x0 - TILEBORDER + colMin + 1) & 1), indx = row * CACHESIZE + col, c = FC(y0 - TILEBORDER + row, x0 - TILEBORDER + col + 1), d = 2 - c; col < colMax; col += 2, indx += 2) { - assert(indx >= 0 && indx < u * u && c >= 0 && c < 4); - -//Jacek comment: two multiplications (in total) less - image[indx][c] = image[indx][1] + (image[indx + 1][c] + image[indx - 1][c] - (image[indx + 1][1] + image[indx - 1][1])) * 0.5f; - image[indx][d] = image[indx][1] + (image[indx + u][d] + image[indx - u][d] - (image[indx + u][1] + image[indx - u][1])) * 0.5f; - - -/* original - image[indx][c] = (2.f * image[indx][1] - image[indx + 1][1] - image[indx - 1][1] + image[indx + 1][c] + image[indx - 1][c]) * 0.5f; - image[indx][d] = (2.f * image[indx][1] - image[indx + u][1] - image[indx - u][1] + image[indx + u][d] + image[indx - u][d]) * 0.5f; -*/ - } -} - -// green correction -void RawImageSource::dcb_hid2(float (*image)[3], int x0, int y0) -{ - const int v = 2 * CACHESIZE; - int rowMin, colMin, rowMax, colMax; - dcb_initTileLimits(colMin, rowMin, colMax, rowMax, x0, y0, 2); - - for (int row = rowMin; row < rowMax; row++) { - for (int col = colMin + (FC(y0 - TILEBORDER + row, x0 - TILEBORDER + colMin) & 1), indx = row * CACHESIZE + col, c = FC(y0 - TILEBORDER + row, x0 - TILEBORDER + col); col < colMax; col += 2, indx += 2) { - assert(indx - v >= 0 && indx + v < CACHESIZE * CACHESIZE); - -//Jacek comment: one multiplication less - image[indx][1] = image[indx][c] + - (image[indx + v][1] + image[indx - v][1] + image[indx - 2][1] + image[indx + 2][1] - - (image[indx + v][c] + image[indx - v][c] + image[indx - 2][c] + image[indx + 2][c])) * 0.25f; - -/* original - image[indx][1] = (image[indx + v][1] + image[indx - v][1] + image[indx - 2][1] + image[indx + 2][1]) * 0.25f + - image[indx][c] - ( image[indx + v][c] + image[indx - v][c] + image[indx - 2][c] + image[indx + 2][c]) * 0.25f; -*/ - } - } -} - -// green is used to create -// an interpolation direction map -// 1 = vertical -// 0 = horizontal -// saved in image[][3] - -// seems at least 2 persons implemented some code, as this one has different coding style, could be unified -// I don't know if *pix is faster than a loop working on image[] directly -void RawImageSource::dcb_map(float (*image)[3], uint8_t *map, int x0, int y0) -{ - const int u = 3 * CACHESIZE; - int rowMin, colMin, rowMax, colMax; - dcb_initTileLimits(colMin, rowMin, colMax, rowMax, x0, y0, 2); - - for (int row = rowMin; row < rowMax; row++) { - for (int col = colMin, indx = row * CACHESIZE + col; col < colMax; col++, indx++) { - float *pix = &(image[indx][1]); - - assert(indx >= 0 && indx < u * u); - - // comparing 4 * a to (b+c+d+e) instead of a to (b+c+d+e)/4 is faster because divisions are slow - if ( 4 * (*pix) > ( (pix[-3] + pix[+3]) + (pix[-u] + pix[+u])) ) { - map[indx] = ((min(pix[-3], pix[+3]) + (pix[-3] + pix[+3]) ) < (min(pix[-u], pix[+u]) + (pix[-u] + pix[+u]))); - } else { - map[indx] = ((max(pix[-3], pix[+3]) + (pix[-3] + pix[+3]) ) > (max(pix[-u], pix[+u]) + (pix[-u] + pix[+u]))); - } - } - } -} - -// interpolated green pixels are corrected using the map -void RawImageSource::dcb_correction(float (*image)[3], uint8_t *map, int x0, int y0) -{ - const int u = CACHESIZE, v = 2 * CACHESIZE; - int rowMin, colMin, rowMax, colMax; - dcb_initTileLimits(colMin, rowMin, colMax, rowMax, x0, y0, 2); - - for (int row = rowMin; row < rowMax; row++) { - for (int indx = row * CACHESIZE + colMin + (FC(y0 - TILEBORDER + row, x0 - TILEBORDER + colMin) & 1); indx < row * CACHESIZE + colMax; indx += 2) { -// for (int col = colMin + (FC(y0 - TILEBORDER + row, x0 - TILEBORDER + colMin) & 1), indx = row * CACHESIZE + col; col < colMax; col += 2, indx += 2) { - float current = 4 * map[indx] + - 2 * (map[indx + u] + map[indx - u] + map[indx + 1] + map[indx - 1]) + - map[indx + v] + map[indx - v] + map[indx + 2] + map[indx - 2]; - - assert(indx >= 0 && indx < u * u); - image[indx][1] = ((16.f - current) * (image[indx - 1][1] + image[indx + 1][1]) + current * (image[indx - u][1] + image[indx + u][1]) ) * 0.03125f; -// image[indx][1] = ((16.f - current) * (image[indx - 1][1] + image[indx + 1][1]) * 0.5f + current * (image[indx - u][1] + image[indx + u][1]) * 0.5f ) * 0.0625f; - } - } -} - -// R and B smoothing using green contrast, all pixels except 2 pixel wide border - -// again code with *pix, is this kind of calculating faster in C, than this what was commented? -void RawImageSource::dcb_pp(float (*image)[3], int x0, int y0) -{ - const int u = CACHESIZE; - int rowMin, colMin, rowMax, colMax; - dcb_initTileLimits(colMin, rowMin, colMax, rowMax, x0, y0, 2); - - for (int row = rowMin; row < rowMax; row++) - for (int col = colMin, indx = row * CACHESIZE + col; col < colMax; col++, indx++) { -// float r1 = image[indx-1][0] + image[indx+1][0] + image[indx-u][0] + image[indx+u][0] + image[indx-u-1][0] + image[indx+u+1][0] + image[indx-u+1][0] + image[indx+u-1][0]; -// float g1 = image[indx-1][1] + image[indx+1][1] + image[indx-u][1] + image[indx+u][1] + image[indx-u-1][1] + image[indx+u+1][1] + image[indx-u+1][1] + image[indx+u-1][1]; -// float b1 = image[indx-1][2] + image[indx+1][2] + image[indx-u][2] + image[indx+u][2] + image[indx-u-1][2] + image[indx+u+1][2] + image[indx-u+1][2] + image[indx+u-1][2]; - float (*pix)[3] = image + (indx - u - 1); - float r1 = (*pix)[0]; - float g1 = (*pix)[1]; - float b1 = (*pix)[2]; - pix++; - r1 += (*pix)[0]; - g1 += (*pix)[1]; - b1 += (*pix)[2]; - pix++; - r1 += (*pix)[0]; - g1 += (*pix)[1]; - b1 += (*pix)[2]; - pix += CACHESIZE - 2; - r1 += (*pix)[0]; - g1 += (*pix)[1]; - b1 += (*pix)[2]; - pix += 2; - r1 += (*pix)[0]; - g1 += (*pix)[1]; - b1 += (*pix)[2]; - pix += CACHESIZE - 2; - r1 += (*pix)[0]; - g1 += (*pix)[1]; - b1 += (*pix)[2]; - pix++; - r1 += (*pix)[0]; - g1 += (*pix)[1]; - b1 += (*pix)[2]; - pix++; - r1 += (*pix)[0]; - g1 += (*pix)[1]; - b1 += (*pix)[2]; - r1 *= 0.125f; - g1 *= 0.125f; - b1 *= 0.125f; - r1 += ( image[indx][1] - g1 ); - b1 += ( image[indx][1] - g1 ); - - assert(indx >= 0 && indx < u * u); - image[indx][0] = r1; - image[indx][2] = b1; - } -} - -// interpolated green pixels are corrected using the map -// with correction -void RawImageSource::dcb_correction2(float (*image)[3], uint8_t *map, int x0, int y0) -{ - const int u = CACHESIZE, v = 2 * CACHESIZE; - int rowMin, colMin, rowMax, colMax; - dcb_initTileLimits(colMin, rowMin, colMax, rowMax, x0, y0, 4); - - for (int row = rowMin; row < rowMax; row++) { - for (int indx = row * CACHESIZE + colMin + (FC(y0 - TILEBORDER + row, x0 - TILEBORDER + colMin) & 1), c = FC(y0 - TILEBORDER + row, x0 - TILEBORDER + colMin + (FC(y0 - TILEBORDER + row, x0 - TILEBORDER + colMin) & 1)); indx < row * CACHESIZE + colMax; indx += 2) { - // map values are uint8_t either 0 or 1. Adding them using integer instructions is perfectly valid and fast. Final result is converted to float then - float current = 4 * map[indx] + - 2 * (map[indx + u] + map[indx - u] + map[indx + 1] + map[indx - 1]) + - map[indx + v] + map[indx - v] + map[indx + 2] + map[indx - 2]; - - assert(indx >= 0 && indx < u * u); - -// Jacek comment: works now, and has 3 float mults and 9 float adds - image[indx][1] = image[indx][c] + - ((16.f - current) * (image[indx - 1][1] + image[indx + 1][1] - (image[indx + 2][c] + image[indx - 2][c])) - + current * (image[indx - u][1] + image[indx + u][1] - (image[indx + v][c] + image[indx - v][c]))) * 0.03125f; - - - // 4 float mults and 9 float adds - // Jacek comment: not mathematically identical to original -/* image[indx][1] = 16.f * image[indx][c] + - ((16.f - current) * ((image[indx - 1][1] + image[indx + 1][1]) - - (image[indx + 2][c] + image[indx - 2][c])) - + current * ((image[indx - u][1] + image[indx + u][1]) - (image[indx + v][c] + image[indx - v][c]))) * 0.03125f; -*/ - // 7 float mults and 10 float adds - // original code -/* - image[indx][1] = ((16.f - current) * ((image[indx - 1][1] + image[indx + 1][1]) * 0.5f - + image[indx][c] - (image[indx + 2][c] + image[indx - 2][c]) * 0.5f) - + current * ((image[indx - u][1] + image[indx + u][1]) * 0.5f + image[indx][c] - (image[indx + v][c] + image[indx - v][c]) * 0.5f)) * 0.0625f; -*/ - } - } -} - -// image refinement -void RawImageSource::dcb_refinement(float (*image)[3], uint8_t *map, int x0, int y0) -{ - const int u = CACHESIZE, v = 2 * CACHESIZE; - int rowMin, colMin, rowMax, colMax; - dcb_initTileLimits(colMin, rowMin, colMax, rowMax, x0, y0, 4); - - float f0, f1, f2, g1, h0, h1, h2, g2; - - for (int row = rowMin; row < rowMax; row++) - for (int col = colMin + (FC(y0 - TILEBORDER + row, x0 - TILEBORDER + colMin) & 1), indx = row * CACHESIZE + col, c = FC(y0 - TILEBORDER + row, x0 - TILEBORDER + col); col < colMax; col += 2, indx += 2) { - - float current = 4 * map[indx] + - 2 * (map[indx + u] + map[indx - u] + map[indx + 1] + map[indx - 1]) - + map[indx + v] + map[indx - v] + map[indx - 2] + map[indx + 2]; - - float currPix = image[indx][c]; - - f0 = (float)(image[indx - u][1] + image[indx + u][1]) / (1.f + 2.f * currPix); - f1 = 2.f * image[indx - u][1] / (1.f + image[indx - v][c] + currPix); - f2 = 2.f * image[indx + u][1] / (1.f + image[indx + v][c] + currPix); - - g1 = f0 + f1 + f2; - - h0 = (float)(image[indx - 1][1] + image[indx + 1][1]) / (1.f + 2.f * currPix); - h1 = 2.f * image[indx - 1][1] / (1.f + image[indx - 2][c] + currPix); - h2 = 2.f * image[indx + 1][1] / (1.f + image[indx + 2][c] + currPix); - - g2 = h0 + h1 + h2; - - // new green value - assert(indx >= 0 && indx < u * u); - currPix *= (current * g1 + (16.f - current) * g2) / 48.f; - - // get rid of the overshot pixels - float minVal = min(image[indx - 1][1], min(image[indx + 1][1], min(image[indx - u][1], image[indx + u][1]))); - float maxVal = max(image[indx - 1][1], max(image[indx + 1][1], max(image[indx - u][1], image[indx + u][1]))); - - image[indx][1] = LIM(currPix, minVal, maxVal); - - } -} - -// missing colours are interpolated using high quality algorithm by Luis Sanz Rodriguez -void RawImageSource::dcb_color_full(float (*image)[3], int x0, int y0, float (*chroma)[2]) -{ - const int u = CACHESIZE, w = 3 * CACHESIZE; - int rowMin, colMin, rowMax, colMax; - dcb_initTileLimits(colMin, rowMin, colMax, rowMax, x0, y0, 3); - - float f[4], g[4]; - - for (int row = 1; row < CACHESIZE - 1; row++) - for (int col = 1 + (FC(y0 - TILEBORDER + row, x0 - TILEBORDER + 1) & 1), indx = row * CACHESIZE + col, c = FC(y0 - TILEBORDER + row, x0 - TILEBORDER + col), d = c / 2; col < CACHESIZE - 1; col += 2, indx += 2) { - assert(indx >= 0 && indx < u * u && c >= 0 && c < 4); - chroma[indx][d] = image[indx][c] - image[indx][1]; - } - - for (int row = rowMin; row < rowMax; row++) - for (int col = colMin + (FC(y0 - TILEBORDER + row, x0 - TILEBORDER + colMin) & 1), indx = row * CACHESIZE + col, c = 1 - FC(y0 - TILEBORDER + row, x0 - TILEBORDER + col) / 2; col < colMax; col += 2, indx += 2) { - f[0] = 1.f / (float)(1.f + fabs(chroma[indx - u - 1][c] - chroma[indx + u + 1][c]) + fabs(chroma[indx - u - 1][c] - chroma[indx - w - 3][c]) + fabs(chroma[indx + u + 1][c] - chroma[indx - w - 3][c])); - f[1] = 1.f / (float)(1.f + fabs(chroma[indx - u + 1][c] - chroma[indx + u - 1][c]) + fabs(chroma[indx - u + 1][c] - chroma[indx - w + 3][c]) + fabs(chroma[indx + u - 1][c] - chroma[indx - w + 3][c])); - f[2] = 1.f / (float)(1.f + fabs(chroma[indx + u - 1][c] - chroma[indx - u + 1][c]) + fabs(chroma[indx + u - 1][c] - chroma[indx + w + 3][c]) + fabs(chroma[indx - u + 1][c] - chroma[indx + w - 3][c])); - f[3] = 1.f / (float)(1.f + fabs(chroma[indx + u + 1][c] - chroma[indx - u - 1][c]) + fabs(chroma[indx + u + 1][c] - chroma[indx + w - 3][c]) + fabs(chroma[indx - u - 1][c] - chroma[indx + w + 3][c])); - g[0] = 1.325f * chroma[indx - u - 1][c] - 0.175f * chroma[indx - w - 3][c] - 0.075f * (chroma[indx - w - 1][c] + chroma[indx - u - 3][c]); - g[1] = 1.325f * chroma[indx - u + 1][c] - 0.175f * chroma[indx - w + 3][c] - 0.075f * (chroma[indx - w + 1][c] + chroma[indx - u + 3][c]); - g[2] = 1.325f * chroma[indx + u - 1][c] - 0.175f * chroma[indx + w - 3][c] - 0.075f * (chroma[indx + w - 1][c] + chroma[indx + u - 3][c]); - g[3] = 1.325f * chroma[indx + u + 1][c] - 0.175f * chroma[indx + w + 3][c] - 0.075f * (chroma[indx + w + 1][c] + chroma[indx + u + 3][c]); - -// g[0] = 1.325f * chroma[indx - u - 1][c] - 0.175f * chroma[indx - w - 3][c] - 0.075f * chroma[indx - w - 1][c] - 0.075f * chroma[indx - u - 3][c]; -// g[1] = 1.325f * chroma[indx - u + 1][c] - 0.175f * chroma[indx - w + 3][c] - 0.075f * chroma[indx - w + 1][c] - 0.075f * chroma[indx - u + 3][c]; -// g[2] = 1.325f * chroma[indx + u - 1][c] - 0.175f * chroma[indx + w - 3][c] - 0.075f * chroma[indx + w - 1][c] - 0.075f * chroma[indx + u - 3][c]; -// g[3] = 1.325f * chroma[indx + u + 1][c] - 0.175f * chroma[indx + w + 3][c] - 0.075f * chroma[indx + w + 1][c] - 0.075f * chroma[indx + u + 3][c]; - - assert(indx >= 0 && indx < u * u && c >= 0 && c < 2); - chroma[indx][c] = (f[0] * g[0] + f[1] * g[1] + f[2] * g[2] + f[3] * g[3]) / (f[0] + f[1] + f[2] + f[3]); - } - - for (int row = rowMin; row < rowMax; row++) - for (int col = colMin + (FC(y0 - TILEBORDER + row, x0 - TILEBORDER + colMin + 1) & 1), indx = row * CACHESIZE + col, c = FC(y0 - TILEBORDER + row, x0 - TILEBORDER + col + 1) / 2; col < colMax; col += 2, indx += 2) - for(int d = 0; d <= 1; c = 1 - c, d++) { - f[0] = 1.f / (1.f + fabs(chroma[indx - u][c] - chroma[indx + u][c]) + fabs(chroma[indx - u][c] - chroma[indx - w][c]) + fabs(chroma[indx + u][c] - chroma[indx - w][c])); - f[1] = 1.f / (1.f + fabs(chroma[indx + 1][c] - chroma[indx - 1][c]) + fabs(chroma[indx + 1][c] - chroma[indx + 3][c]) + fabs(chroma[indx - 1][c] - chroma[indx + 3][c])); - f[2] = 1.f / (1.f + fabs(chroma[indx - 1][c] - chroma[indx + 1][c]) + fabs(chroma[indx - 1][c] - chroma[indx - 3][c]) + fabs(chroma[indx + 1][c] - chroma[indx - 3][c])); - f[3] = 1.f / (1.f + fabs(chroma[indx + u][c] - chroma[indx - u][c]) + fabs(chroma[indx + u][c] - chroma[indx + w][c]) + fabs(chroma[indx - u][c] - chroma[indx + w][c])); - - g[0] = intp(0.875f, chroma[indx - u][c], chroma[indx - w][c]); - g[1] = intp(0.875f, chroma[indx + 1][c], chroma[indx + 3][c]); - g[2] = intp(0.875f, chroma[indx - 1][c], chroma[indx - 3][c]); - g[3] = intp(0.875f, chroma[indx + u][c], chroma[indx + w][c]); - -// g[0] = 0.875f * chroma[indx - u][c] + 0.125f * chroma[indx - w][c]; -// g[1] = 0.875f * chroma[indx + 1][c] + 0.125f * chroma[indx + 3][c]; -// g[2] = 0.875f * chroma[indx - 1][c] + 0.125f * chroma[indx - 3][c]; -// g[3] = 0.875f * chroma[indx + u][c] + 0.125f * chroma[indx + w][c]; - - assert(indx >= 0 && indx < u * u && c >= 0 && c < 2); - chroma[indx][c] = (f[0] * g[0] + f[1] * g[1] + f[2] * g[2] + f[3] * g[3]) / (f[0] + f[1] + f[2] + f[3]); - } - - for(int row = rowMin; row < rowMax; row++) - for(int col = colMin, indx = row * CACHESIZE + col; col < colMax; col++, indx++) { - assert(indx >= 0 && indx < u * u); - - image[indx][0] = chroma[indx][0] + image[indx][1]; - image[indx][2] = chroma[indx][1] + image[indx][1]; - } -} - -// DCB demosaicing main routine -void RawImageSource::dcb_demosaic(int iterations, bool dcb_enhance) -{ -BENCHFUN - double currentProgress = 0.0; - - if(plistener) { - plistener->setProgressStr (Glib::ustring::compose(M("TP_RAW_DMETHOD_PROGRESSBAR"), RAWParams::BayerSensor::getMethodString(RAWParams::BayerSensor::Method::DCB))); - plistener->setProgress (currentProgress); - } - - int wTiles = W / TILESIZE + (W % TILESIZE ? 1 : 0); - int hTiles = H / TILESIZE + (H % TILESIZE ? 1 : 0); - int numTiles = wTiles * hTiles; - int tilesDone = 0; - constexpr int cldf = 2; // factor to multiply cache line distance. 1 = 64 bytes, 2 = 128 bytes ... - -#ifdef _OPENMP - #pragma omp parallel -#endif -{ - // assign working space - char *buffer0 = (char *) malloc(5 * sizeof(float) * CACHESIZE * CACHESIZE + sizeof(uint8_t) * CACHESIZE * CACHESIZE + 3 * cldf * 64 + 63); - // aligned to 64 byte boundary - char *data = (char*)( ( uintptr_t(buffer0) + uintptr_t(63)) / 64 * 64); - - float (*tile)[3] = (float(*)[3]) data; - float (*buffer)[2] = (float(*)[2]) ((char*)tile + sizeof(float) * CACHESIZE * CACHESIZE * 3 + cldf * 64); - float (*chrm)[2] = (float(*)[2]) (buffer); // No overlap in usage of buffer and chrm means we can reuse buffer - uint8_t *map = (uint8_t*) ((char*)buffer + sizeof(float) * CACHESIZE * CACHESIZE * 2 + cldf * 64); - -#ifdef _OPENMP - #pragma omp for schedule(dynamic) nowait -#endif - - for( int iTile = 0; iTile < numTiles; iTile++) { - int xTile = iTile % wTiles; - int yTile = iTile / wTiles; - int x0 = xTile * TILESIZE; - int y0 = yTile * TILESIZE; - - memset(tile, 0, CACHESIZE * CACHESIZE * sizeof * tile); - memset(map, 0, CACHESIZE * CACHESIZE * sizeof * map); - - fill_raw( tile, x0, y0, rawData ); - - if( !xTile || !yTile || xTile == wTiles - 1 || yTile == hTiles - 1) { - fill_border(tile, 6, x0, y0); - } - - copy_to_buffer(buffer, tile); - dcb_hid(tile, x0, y0); - - for (int i = iterations; i > 0; i--) { - dcb_hid2(tile, x0, y0); - dcb_hid2(tile, x0, y0); - dcb_hid2(tile, x0, y0); - dcb_map(tile, map, x0, y0); - dcb_correction(tile, map, x0, y0); - } - - dcb_color(tile, x0, y0); - dcb_pp(tile, x0, y0); - dcb_map(tile, map, x0, y0); - dcb_correction2(tile, map, x0, y0); - dcb_map(tile, map, x0, y0); - dcb_correction(tile, map, x0, y0); - dcb_color(tile, x0, y0); - dcb_map(tile, map, x0, y0); - dcb_correction(tile, map, x0, y0); - dcb_map(tile, map, x0, y0); - dcb_correction(tile, map, x0, y0); - dcb_map(tile, map, x0, y0); - restore_from_buffer(tile, buffer); - - if (!dcb_enhance) - dcb_color(tile, x0, y0); - else - { - memset(chrm, 0, CACHESIZE * CACHESIZE * sizeof * chrm); - dcb_refinement(tile, map, x0, y0); - dcb_color_full(tile, x0, y0, chrm); - } - - /* - dcb_hid(tile, buffer, buffer2, x0, y0); - dcb_color(tile, x0, y0); - - copy_to_buffer(buffer, tile); - - for (int i = iterations; i > 0; i--) { - dcb_hid2(tile, x0, y0); - dcb_hid2(tile, x0, y0); - dcb_hid2(tile, x0, y0); - dcb_map(tile, x0, y0); - dcb_correction(tile, x0, y0); - } - - dcb_color(tile, x0, y0); - dcb_pp(tile, x0, y0); - dcb_map(tile, x0, y0); - dcb_correction2(tile, x0, y0); - dcb_map(tile, x0, y0); - dcb_correction(tile, x0, y0); - dcb_color(tile, x0, y0); - dcb_map(tile, x0, y0); - dcb_correction(tile, x0, y0); - dcb_map(tile, x0, y0); - dcb_correction(tile, x0, y0); - dcb_map(tile, x0, y0); - restore_from_buffer(tile, buffer); - dcb_color_full(tile, x0, y0, chrm); - - if (dcb_enhance) { - dcb_refinement(tile, x0, y0); - dcb_color_full(tile, x0, y0, chrm); - } -*/ - for(int y = 0; y < TILESIZE && y0 + y < H; y++) { - for (int j = 0; j < TILESIZE && x0 + j < W; j++) { - red[y0 + y][x0 + j] = tile[(y + TILEBORDER) * CACHESIZE + TILEBORDER + j][0]; - green[y0 + y][x0 + j] = tile[(y + TILEBORDER) * CACHESIZE + TILEBORDER + j][1]; - blue[y0 + y][x0 + j] = tile[(y + TILEBORDER) * CACHESIZE + TILEBORDER + j][2]; - } - } - -#ifdef _OPENMP - - if(omp_get_thread_num() == 0) -#endif - { - if( plistener && double(tilesDone) / numTiles > currentProgress) { - currentProgress += 0.1; // Show progress each 10% - plistener->setProgress (currentProgress); - } - } - -#ifdef _OPENMP - #pragma omp atomic -#endif - tilesDone++; - } - free(buffer0); -} - - if(plistener) { - plistener->setProgress (1.0); - } -} - -#undef TILEBORDER -#undef TILESIZE -#undef CACHESIZE -} /* namespace */ From 928309f3aab7adc520d2676970cf9dca85e8308e Mon Sep 17 00:00:00 2001 From: Hombre Date: Sat, 2 Jun 2018 02:34:33 +0200 Subject: [PATCH 11/42] GUI code cleanup - Remove usage of std::numeric_limits::max() in GUI which bring unwanted behavior. - Put the PixelShift options in a Gtk::Frame (requested on IRC) - Add the fast_export raw options to the GUI (was created but not added to the container). Incidentally, fix a memory leak. - Add a missing History message --- rtdata/languages/default | 1 + rtgui/bayerprocess.cc | 98 +++++++++++++++++++--------------------- rtgui/bayerprocess.h | 2 +- rtgui/exportpanel.cc | 14 +++--- rtgui/flatfield.cc | 16 ++----- rtgui/xtransprocess.cc | 30 ++++-------- 6 files changed, 71 insertions(+), 90 deletions(-) diff --git a/rtdata/languages/default b/rtdata/languages/default index 8231932fb..3621fc806 100644 --- a/rtdata/languages/default +++ b/rtdata/languages/default @@ -736,6 +736,7 @@ HISTORY_MSG_LOCALCONTRAST_LIGHTNESS;Local Contrast - Lightness HISTORY_MSG_LOCALCONTRAST_RADIUS;Local Contrast - Radius HISTORY_MSG_METADATA_MODE;Metadata copy mode HISTORY_MSG_MICROCONTRAST_CONTRAST;Microcontrast - Contrast threshold +HISTORY_MSG_PIXELSHIFT_DEMOSAIC;PS - Demosaic method for motion HISTORY_MSG_PREPROCESS_LINEDENOISE_DIRECTION;Line noise filter direction HISTORY_MSG_PREPROCESS_PDAFLINESFILTER;PDAF lines filter HISTORY_MSG_PRSHARPEN_CONTRAST;PRS - Contrast threshold diff --git a/rtgui/bayerprocess.cc b/rtgui/bayerprocess.cc index 23e848fc6..72fa4c42f 100644 --- a/rtgui/bayerprocess.cc +++ b/rtgui/bayerprocess.cc @@ -113,18 +113,24 @@ BayerProcess::BayerProcess () : FoldableToolPanel(this, "bayerprocess", M("TP_RA dualDemosaicOptions->pack_start(*dualDemosaicContrast); pack_start( *dualDemosaicOptions, Gtk::PACK_SHRINK, 4); - pixelShiftFrame = Gtk::manage (new Gtk::VBox ()); - pixelShiftFrame->set_border_width(0); + + // -------------------- PixelShift ---------------------- + + + pixelShiftFrame = Gtk::manage(new Gtk::Frame(M("TP_RAW_PIXELSHIFT"))); + + Gtk::VBox *pixelShiftMainVBox = Gtk::manage (new Gtk::VBox ()); + pixelShiftMainVBox->set_border_width(0); pixelShiftEqualBright = Gtk::manage (new CheckBox(M("TP_RAW_PIXELSHIFTEQUALBRIGHT"), multiImage)); pixelShiftEqualBright->setCheckBoxListener (this); pixelShiftEqualBright->set_tooltip_text (M("TP_RAW_PIXELSHIFTEQUALBRIGHT_TOOLTIP")); - pixelShiftFrame->pack_start(*pixelShiftEqualBright); + pixelShiftMainVBox->pack_start(*pixelShiftEqualBright); pixelShiftEqualBrightChannel = Gtk::manage (new CheckBox(M("TP_RAW_PIXELSHIFTEQUALBRIGHTCHANNEL"), multiImage)); pixelShiftEqualBrightChannel->setCheckBoxListener (this); pixelShiftEqualBrightChannel->set_tooltip_text (M("TP_RAW_PIXELSHIFTEQUALBRIGHTCHANNEL_TOOLTIP")); - pixelShiftFrame->pack_start(*pixelShiftEqualBrightChannel); + pixelShiftMainVBox->pack_start(*pixelShiftEqualBrightChannel); Gtk::HBox* hb3 = Gtk::manage (new Gtk::HBox ()); hb3->pack_start (*Gtk::manage (new Gtk::Label ( M("TP_RAW_PIXELSHIFTMOTIONMETHOD") + ": ")), Gtk::PACK_SHRINK, 4); @@ -135,7 +141,7 @@ BayerProcess::BayerProcess () : FoldableToolPanel(this, "bayerprocess", M("TP_RA pixelShiftMotionMethod->set_active(toUnderlying(RAWParams::BayerSensor::PSMotionCorrectionMethod::AUTO)); pixelShiftMotionMethod->show(); hb3->pack_start(*pixelShiftMotionMethod); - pixelShiftFrame->pack_start(*hb3); + pixelShiftMainVBox->pack_start(*hb3); pixelShiftOptions = Gtk::manage (new Gtk::VBox ()); pixelShiftOptions->set_border_width(0); @@ -143,12 +149,12 @@ BayerProcess::BayerProcess () : FoldableToolPanel(this, "bayerprocess", M("TP_RA pixelShiftShowMotion = Gtk::manage (new CheckBox(M("TP_RAW_PIXELSHIFTSHOWMOTION"), multiImage)); pixelShiftShowMotion->setCheckBoxListener (this); pixelShiftShowMotion->set_tooltip_text (M("TP_RAW_PIXELSHIFTSHOWMOTION_TOOLTIP")); - pixelShiftFrame->pack_start(*pixelShiftShowMotion); + pixelShiftMainVBox->pack_start(*pixelShiftShowMotion); pixelShiftShowMotionMaskOnly = Gtk::manage (new CheckBox(M("TP_RAW_PIXELSHIFTSHOWMOTIONMASKONLY"), multiImage)); pixelShiftShowMotionMaskOnly->setCheckBoxListener (this); pixelShiftShowMotionMaskOnly->set_tooltip_text (M("TP_RAW_PIXELSHIFTSHOWMOTIONMASKONLY_TOOLTIP")); - pixelShiftFrame->pack_start(*pixelShiftShowMotionMaskOnly); + pixelShiftMainVBox->pack_start(*pixelShiftShowMotionMaskOnly); Gtk::HBox* hb4 = Gtk::manage (new Gtk::HBox ()); @@ -219,7 +225,8 @@ BayerProcess::BayerProcess () : FoldableToolPanel(this, "bayerprocess", M("TP_RA pixelShiftMedian->set_tooltip_text (M("TP_RAW_PIXELSHIFTMEDIAN_TOOLTIP")); pixelShiftOptions->pack_start(*pixelShiftMedian); - pixelShiftFrame->pack_start(*pixelShiftOptions); + pixelShiftMainVBox->pack_start(*pixelShiftOptions); + pixelShiftFrame->add(*pixelShiftMainVBox); pixelShiftOptions->hide(); pack_start( *pixelShiftFrame, Gtk::PACK_SHRINK, 4); @@ -239,7 +246,6 @@ void BayerProcess::read(const rtengine::procparams::ProcParams* pp, const Params pixelShiftDemosaicMethod->block(true); //allEnhconn.block (true); - method->set_active(std::numeric_limits::max()); imageNumber->set_active(pp->raw.bayersensor.imageNum); for (size_t i = 0; i < procparams::RAWParams::BayerSensor::getMethodStrings().size(); ++i) { @@ -249,7 +255,6 @@ void BayerProcess::read(const rtengine::procparams::ProcParams* pp, const Params break; } } - pixelShiftDemosaicMethod->set_active(std::numeric_limits::max()); for (size_t i = 0; i < procparams::RAWParams::BayerSensor::getPSDemosaicMethodStrings().size(); ++i) { if (pp->raw.bayersensor.pixelShiftDemosaicMethod == procparams::RAWParams::BayerSensor::getPSDemosaicMethodStrings()[i]) { pixelShiftDemosaicMethod->set_active(i); @@ -261,21 +266,23 @@ void BayerProcess::read(const rtengine::procparams::ProcParams* pp, const Params dcbIterations->setValue (pp->raw.bayersensor.dcb_iterations); dcbEnhance->setValue (pp->raw.bayersensor.dcb_enhance); pixelShiftShowMotion->setValue (pp->raw.bayersensor.pixelShiftShowMotion); + pixelShiftShowMotionMaskOnly->setValue (pp->raw.bayersensor.pixelShiftShowMotionMaskOnly); if (!batchMode) { pixelShiftShowMotionMaskOnly->set_sensitive (pp->raw.bayersensor.pixelShiftShowMotion); } - pixelShiftShowMotionMaskOnly->setValue (pp->raw.bayersensor.pixelShiftShowMotionMaskOnly); pixelShiftHoleFill->setValue (pp->raw.bayersensor.pixelShiftHoleFill); pixelShiftMedian->setValue (pp->raw.bayersensor.pixelShiftMedian); pixelShiftGreen->setValue (pp->raw.bayersensor.pixelShiftGreen); pixelShiftBlur->setValue (pp->raw.bayersensor.pixelShiftBlur); + pixelShiftSmooth->setValue (pp->raw.bayersensor.pixelShiftSmoothFactor); if (!batchMode) { pixelShiftSmooth->set_sensitive (pp->raw.bayersensor.pixelShiftBlur); } - pixelShiftSmooth->setValue (pp->raw.bayersensor.pixelShiftSmoothFactor); pixelShiftEqualBright->setValue (pp->raw.bayersensor.pixelShiftEqualBright); - pixelShiftEqualBrightChannel->set_sensitive (pp->raw.bayersensor.pixelShiftEqualBright); pixelShiftEqualBrightChannel->setValue (pp->raw.bayersensor.pixelShiftEqualBrightChannel); + if (!batchMode) { + pixelShiftEqualBrightChannel->set_sensitive (pp->raw.bayersensor.pixelShiftEqualBright); + } pixelShiftNonGreenCross->setValue (pp->raw.bayersensor.pixelShiftNonGreenCross); ccSteps->setValue (pp->raw.bayersensor.ccSteps); lmmseIterations->setValue (pp->raw.bayersensor.lmmse_iterations); @@ -307,7 +314,7 @@ void BayerProcess::read(const rtengine::procparams::ProcParams* pp, const Params pixelShiftSigma->setEditedState ( pedited->raw.bayersensor.pixelShiftSigma ? Edited : UnEdited); if(!pedited->raw.bayersensor.method) { - method->set_active(std::numeric_limits::max()); // No name + method->set_active_text(M("GENERAL_UNCHANGED")); } if(!pedited->raw.bayersensor.imageNum) { @@ -319,7 +326,7 @@ void BayerProcess::read(const rtengine::procparams::ProcParams* pp, const Params } if(!pedited->raw.bayersensor.pixelShiftDemosaicMethod) { - pixelShiftDemosaicMethod->set_active(std::numeric_limits::max()); // No name + pixelShiftDemosaicMethod->set_active_text(M("GENERAL_UNCHANGED")); } } @@ -335,7 +342,7 @@ void BayerProcess::read(const rtengine::procparams::ProcParams* pp, const Params pixelShiftFrame->hide(); } - // Flase color suppression is applied to all demozaicing method, so don't hide anything + // False color suppression is applied to all demozaicing method, so don't hide anything /*if (pp->raw.bayersensor.method == procparams::RAWParams::BayerSensor::getMethodString(procparams::RAWParams::BayerSensor::Method::EAHD) || pp->raw.bayersensor.method == procparams::RAWParams::BayerSensor::getMethodString(procparams::RAWParams::BayerSensor::Method::HPHD) || pp->raw.bayersensor.method == procparams::RAWParams::BayerSensor::getMethodString(procparams::RAWParams::BayerSensor::Method::VNG4)) @@ -377,24 +384,24 @@ void BayerProcess::write( rtengine::procparams::ProcParams* pp, ParamsEdited* pe pp->raw.bayersensor.pixelShiftNonGreenCross = pixelShiftNonGreenCross->getLastActive (); int currentRow = method->get_active_row_number(); - if( currentRow >= 0 && currentRow < std::numeric_limits::max()) { + if( currentRow >= 0 && method->get_active_text() != M("GENERAL_UNCHANGED")) { pp->raw.bayersensor.method = procparams::RAWParams::BayerSensor::getMethodString(RAWParams::BayerSensor::Method(currentRow)); } currentRow = imageNumber->get_active_row_number(); - if (currentRow < 4) { + if (currentRow >= 0 && imageNumber->get_active_text() != M("GENERAL_UNCHANGED")) { pp->raw.bayersensor.imageNum = currentRow; } currentRow = pixelShiftDemosaicMethod->get_active_row_number(); - if( currentRow >= 0 && currentRow < std::numeric_limits::max()) { + if( currentRow >= 0 && pixelShiftDemosaicMethod->get_active_text() != M("GENERAL_UNCHANGED")) { pp->raw.bayersensor.pixelShiftDemosaicMethod = procparams::RAWParams::BayerSensor::getPSDemosaicMethodString(RAWParams::BayerSensor::PSDemosaicMethod(currentRow)); } if (pedited) { pedited->raw.bayersensor.ccSteps = ccSteps->getEditedState (); - pedited->raw.bayersensor.method = method->get_active_row_number() != std::numeric_limits::max(); + pedited->raw.bayersensor.method = method->get_active_text() != M("GENERAL_UNCHANGED"); pedited->raw.bayersensor.imageNum = imageNumber->get_active_text() != M("GENERAL_UNCHANGED"); pedited->raw.bayersensor.dcbIterations = dcbIterations->getEditedState (); pedited->raw.bayersensor.dcbEnhance = !dcbEnhance->get_inconsistent(); @@ -402,7 +409,7 @@ void BayerProcess::write( rtengine::procparams::ProcParams* pp, ParamsEdited* pe pedited->raw.bayersensor.lmmseIterations = lmmseIterations->getEditedState (); pedited->raw.bayersensor.dualDemosaicContrast = dualDemosaicContrast->getEditedState (); pedited->raw.bayersensor.pixelShiftMotionCorrectionMethod = pixelShiftMotionMethod->get_active_text() != M("GENERAL_UNCHANGED"); - pedited->raw.bayersensor.pixelShiftDemosaicMethod = pixelShiftDemosaicMethod->get_active_row_number() != std::numeric_limits::max(); + pedited->raw.bayersensor.pixelShiftDemosaicMethod = pixelShiftDemosaicMethod->get_active_text() != M("GENERAL_UNCHANGED"); pedited->raw.bayersensor.pixelShiftEperIso = pixelShiftEperIso->getEditedState (); pedited->raw.bayersensor.pixelShiftSigma = pixelShiftSigma->getEditedState (); pedited->raw.bayersensor.pixelShiftShowMotion = !pixelShiftShowMotion->get_inconsistent(); @@ -443,11 +450,11 @@ void BayerProcess::trimValues (rtengine::procparams::ProcParams* pp) void BayerProcess::setBatchMode(bool batchMode) { method->append (M("GENERAL_UNCHANGED")); - method->set_active(std::numeric_limits::max()); // No name + method->set_active_text(M("GENERAL_UNCHANGED")); // No name pixelShiftMotionMethod->append (M("GENERAL_UNCHANGED")); pixelShiftMotionMethod->set_active_text (M("GENERAL_UNCHANGED")); pixelShiftDemosaicMethod->append (M("GENERAL_UNCHANGED")); - pixelShiftDemosaicMethod->set_active(std::numeric_limits::max()); // No name + pixelShiftDemosaicMethod->set_active_text(M("GENERAL_UNCHANGED")); // No name imageNumber->append (M("GENERAL_UNCHANGED")); imageNumber->set_active_text (M("GENERAL_UNCHANGED")); ToolPanel::setBatchMode (batchMode); @@ -508,29 +515,29 @@ void BayerProcess::adjusterChanged (Adjuster* a, double newval) void BayerProcess::methodChanged () { - const int curSelection = method->get_active_row_number(); - const RAWParams::BayerSensor::Method method = RAWParams::BayerSensor::Method(curSelection); + const int currentSelection = method->get_active_row_number(); + const RAWParams::BayerSensor::Method currentMethod = RAWParams::BayerSensor::Method(currentSelection); if (!batchMode) { - if (method == procparams::RAWParams::BayerSensor::Method::DCB) { + if (currentMethod == procparams::RAWParams::BayerSensor::Method::DCB) { dcbOptions->show(); } else { dcbOptions->hide(); } - if (method == procparams::RAWParams::BayerSensor::Method::LMMSE) { + if (currentMethod == procparams::RAWParams::BayerSensor::Method::LMMSE) { lmmseOptions->show(); } else { lmmseOptions->hide(); } - if (method == procparams::RAWParams::BayerSensor::Method::AMAZEVNG4) { + if (currentMethod == procparams::RAWParams::BayerSensor::Method::AMAZEVNG4) { dualDemosaicOptions->show(); } else { dualDemosaicOptions->hide(); } - if (method == procparams::RAWParams::BayerSensor::Method::PIXELSHIFT) { + if (currentMethod == procparams::RAWParams::BayerSensor::Method::PIXELSHIFT) { if(pixelShiftMotionMethod->get_active_row_number() == 2) { pixelShiftOptions->show(); } else { @@ -542,34 +549,21 @@ void BayerProcess::methodChanged () } } - Glib::ustring methodName = ""; - bool ppreq = false; + oldMethod = currentSelection; - if (curSelection >= 0 && curSelection < std::numeric_limits::max()) { - methodName = procparams::RAWParams::BayerSensor::getMethodString(method); - - if (method == procparams::RAWParams::BayerSensor::Method::MONO || RAWParams::BayerSensor::Method(oldMethod) == procparams::RAWParams::BayerSensor::Method::MONO) { - ppreq = true; - } - } - - oldMethod = curSelection; - - if (listener) { - listener->panelChanged (ppreq ? EvDemosaicMethodPreProc : EvDemosaicMethod, methodName); + if (listener && method->get_active_row_number() >= 0) { + listener->panelChanged ( + currentMethod == procparams::RAWParams::BayerSensor::Method::MONO || RAWParams::BayerSensor::Method(oldMethod) == procparams::RAWParams::BayerSensor::Method::MONO + ? EvDemosaicMethodPreProc + : EvDemosaicMethod, method->get_active_text()); } } void BayerProcess::pixelShiftDemosaicMethodChanged () { - if (listener) { - const int curSelection = pixelShiftDemosaicMethod->get_active_row_number(); - if (curSelection >= 0 && curSelection < std::numeric_limits::max()) { - const RAWParams::BayerSensor::PSDemosaicMethod method = RAWParams::BayerSensor::PSDemosaicMethod(curSelection); - Glib::ustring methodName = procparams::RAWParams::BayerSensor::getPSDemosaicMethodString(method);; - listener->panelChanged (EvDemosaicPixelshiftDemosaicMethod, methodName); - } + if (listener && pixelShiftDemosaicMethod->get_active_row_number() >= 0) { + listener->panelChanged (EvDemosaicPixelshiftDemosaicMethod, pixelShiftDemosaicMethod->get_active_text()); } } @@ -646,13 +640,13 @@ void BayerProcess::pixelShiftMotionMethodChanged () pixelShiftOptions->show(); pixelShiftShowMotion->show(); pixelShiftShowMotionMaskOnly->show(); - } else { + } else if(pixelShiftMotionMethod->get_active_row_number() > 0) { pixelShiftOptions->hide(); pixelShiftShowMotion->show(); pixelShiftShowMotionMaskOnly->show(); } } - if (listener) { + if (listener && pixelShiftMotionMethod->get_active_row_number() >= 0) { listener->panelChanged (EvPixelShiftMotionMethod, pixelShiftMotionMethod->get_active_text()); } } diff --git a/rtgui/bayerprocess.h b/rtgui/bayerprocess.h index bfcb99878..2b3e420bc 100644 --- a/rtgui/bayerprocess.h +++ b/rtgui/bayerprocess.h @@ -39,7 +39,7 @@ protected: CheckBox* dcbEnhance; Gtk::VBox *lmmseOptions; Adjuster* lmmseIterations; - Gtk::VBox *pixelShiftFrame; + Gtk::Frame *pixelShiftFrame; Gtk::VBox *pixelShiftOptions; MyComboBoxText* pixelShiftMotionMethod; MyComboBoxText* pixelShiftDemosaicMethod; diff --git a/rtgui/exportpanel.cc b/rtgui/exportpanel.cc index 75156b56b..6c9b96ab7 100644 --- a/rtgui/exportpanel.cc +++ b/rtgui/exportpanel.cc @@ -60,7 +60,7 @@ ExportPanel::ExportPanel () : listener (nullptr) // ---------------------- Bayer sensor frame ----------------------- - Gtk::Frame *bayerFrame = Gtk::manage ( new Gtk::Frame (M ("TP_RAW_SENSOR_BAYER"))); + Gtk::Frame *bayerFrame = Gtk::manage ( new Gtk::Frame (M ("TP_RAW_SENSOR_BAYER_LABEL"))); Gtk::VBox* bayerFrameVBox = Gtk::manage (new Gtk::VBox ()); Gtk::HBox* hb_raw_bayer_method = Gtk::manage (new Gtk::HBox ()); @@ -83,7 +83,7 @@ ExportPanel::ExportPanel () : listener (nullptr) // ---------------------- Bayer sensor frame ----------------------- - Gtk::Frame *xtransFrame = Gtk::manage ( new Gtk::Frame (M ("TP_RAW_SENSOR_XTRANS"))); + Gtk::Frame *xtransFrame = Gtk::manage ( new Gtk::Frame (M ("TP_RAW_SENSOR_XTRANS_LABEL"))); Gtk::VBox* xtransFrameVBox = Gtk::manage (new Gtk::VBox ()); Gtk::HBox* hb_raw_xtrans_method = Gtk::manage (new Gtk::HBox ()); @@ -130,9 +130,11 @@ ExportPanel::ExportPanel () : listener (nullptr) bayerFrameVBox->pack_start (*bypass_raw_bayer_linenoise, Gtk::PACK_SHRINK, 4); bayerFrameVBox->pack_start (*bypass_raw_bayer_greenthresh, Gtk::PACK_SHRINK, 4); bayerFrame->add (*bayerFrameVBox); + bypass_box->pack_start(*bayerFrame, Gtk::PACK_SHRINK, 4); xtransFrameVBox->pack_start (*hb_raw_xtrans_method, Gtk::PACK_SHRINK, 4); xtransFrame->add (*xtransFrameVBox); + bypass_box->pack_start(*xtransFrame, Gtk::PACK_SHRINK, 4); bypass_box->pack_start (*bypass_raw_ccSteps, Gtk::PACK_SHRINK, 4); bypass_box->pack_start (*bypass_raw_ca, Gtk::PACK_SHRINK, 4); @@ -271,14 +273,14 @@ void ExportPanel::SaveSettingsAsDefault() //saving Bayer demosaic_method int currentRow = raw_bayer_method->get_active_row_number(); - if (currentRow >= 0 && currentRow < std::numeric_limits::max()) { + if (currentRow >= 0) { FE_OPT_STORE_ (options.fastexport_raw_bayer_method, procparams::RAWParams::BayerSensor::getMethodStrings()[currentRow]); } //saving X-Trans demosaic_method currentRow = raw_xtrans_method->get_active_row_number(); - if (currentRow >= 0 && currentRow < std::numeric_limits::max()) { + if (currentRow >= 0) { FE_OPT_STORE_ (options.fastexport_raw_xtrans_method, procparams::RAWParams::XTransSensor::getMethodStrings()[currentRow]); } @@ -332,7 +334,7 @@ void ExportPanel::LoadDefaultSettings() bypass_raw_ff->set_active (options.fastexport_bypass_raw_ff ); // Bayer demosaic method - raw_bayer_method->set_active(std::numeric_limits::max()); + raw_bayer_method->set_active(0); for (size_t i = 0; i < RAWParams::BayerSensor::getMethodStrings().size(); ++i) if (options.fastexport_raw_bayer_method == procparams::RAWParams::BayerSensor::getMethodStrings()[i]) { @@ -341,7 +343,7 @@ void ExportPanel::LoadDefaultSettings() } // X-Trans demosaic method - raw_xtrans_method->set_active(std::numeric_limits::max()); + raw_xtrans_method->set_active(0); for (size_t i = 0; i < procparams::RAWParams::XTransSensor::getMethodStrings().size(); ++i) if (options.fastexport_raw_xtrans_method == procparams::RAWParams::XTransSensor::getMethodStrings()[i]) { diff --git a/rtgui/flatfield.cc b/rtgui/flatfield.cc index 2b57aa470..21b5f319a 100644 --- a/rtgui/flatfield.cc +++ b/rtgui/flatfield.cc @@ -136,7 +136,7 @@ void FlatField::read(const rtengine::procparams::ProcParams* pp, const ParamsEdi flatFieldClipControl->setAutoInconsistent(multiImage && !pedited->raw.ff_AutoClipControl); if( !pedited->raw.ff_BlurType ) { - flatFieldBlurType->set_active(std::numeric_limits::max()); // No name + flatFieldBlurType->set_active_text(M("GENERAL_UNCHANGED")); } } @@ -217,7 +217,7 @@ void FlatField::write( rtengine::procparams::ProcParams* pp, ParamsEdited* pedit int currentRow = flatFieldBlurType->get_active_row_number(); - if( currentRow >= 0 && currentRow < std::numeric_limits::max()) { + if( currentRow >= 0 && flatFieldBlurType->get_active_text() != M("GENERAL_UNCHANGED")) { pp->raw.ff_BlurType = procparams::RAWParams::getFlatFieldBlurTypeStrings()[currentRow]; } @@ -227,7 +227,7 @@ void FlatField::write( rtengine::procparams::ProcParams* pp, ParamsEdited* pedit pedited->raw.ff_BlurRadius = flatFieldBlurRadius->getEditedState (); pedited->raw.ff_clipControl = flatFieldClipControl->getEditedState (); pedited->raw.ff_AutoClipControl = !flatFieldClipControl->getAutoInconsistent(); - pedited->raw.ff_BlurType = flatFieldBlurType->get_active_row_number() != std::numeric_limits::max(); + pedited->raw.ff_BlurType = flatFieldBlurType->get_active_text() != M("GENERAL_UNCHANGED"); } } @@ -340,20 +340,14 @@ void FlatField::flatFieldBlurTypeChanged () const int curSelection = flatFieldBlurType->get_active_row_number(); const RAWParams::FlatFieldBlurType blur_type = RAWParams::FlatFieldBlurType(curSelection); - Glib::ustring s; - - if (curSelection >= 0 && curSelection < std::numeric_limits::max()) { - s = flatFieldBlurType->get_active_text(); - } - if (multiImage || blur_type == procparams::RAWParams::FlatFieldBlurType::AREA) { flatFieldClipControl->show(); } else { flatFieldClipControl->hide(); } - if (listener) { - listener->panelChanged (EvFlatFieldBlurType, s); + if (listener && curSelection >= 0) { + listener->panelChanged (EvFlatFieldBlurType, flatFieldBlurType->get_active_text()); } } diff --git a/rtgui/xtransprocess.cc b/rtgui/xtransprocess.cc index a001758f9..456a7c4d5 100644 --- a/rtgui/xtransprocess.cc +++ b/rtgui/xtransprocess.cc @@ -83,8 +83,6 @@ void XTransProcess::read(const rtengine::procparams::ProcParams* pp, const Param disableListener (); methodconn.block (true); - method->set_active(std::numeric_limits::max()); - for (size_t i = 0; i < RAWParams::XTransSensor::getMethodStrings().size(); ++i) if( pp->raw.xtranssensor.method == RAWParams::XTransSensor::getMethodStrings()[i]) { method->set_active(i); @@ -96,7 +94,7 @@ void XTransProcess::read(const rtengine::procparams::ProcParams* pp, const Param ccSteps->setEditedState (pedited->raw.xtranssensor.ccSteps ? Edited : UnEdited); if( !pedited->raw.xtranssensor.method ) { - method->set_active(std::numeric_limits::max()); // No name + method->set_active_text(M("GENERAL_UNCHANGED")); } } @@ -113,12 +111,12 @@ void XTransProcess::write( rtengine::procparams::ProcParams* pp, ParamsEdited* p int currentRow = method->get_active_row_number(); - if (currentRow >= 0 && currentRow < std::numeric_limits::max()) { + if (currentRow >= 0 && method->get_active_text() != M("GENERAL_UNCHANGED")) { pp->raw.xtranssensor.method = procparams::RAWParams::XTransSensor::getMethodStrings()[currentRow]; } if (pedited) { - pedited->raw.xtranssensor.method = method->get_active_row_number() != std::numeric_limits::max(); + pedited->raw.xtranssensor.method = method->get_active_text() != M("GENERAL_UNCHANGED"); pedited->raw.xtranssensor.ccSteps = ccSteps->getEditedState (); } } @@ -131,7 +129,7 @@ void XTransProcess::setAdjusterBehavior (bool falsecoloradd) void XTransProcess::setBatchMode(bool batchMode) { method->append (M("GENERAL_UNCHANGED")); - method->set_active(std::numeric_limits::max()); // No name + method->set_active_text(M("GENERAL_UNCHANGED")); ToolPanel::setBatchMode (batchMode); ccSteps->showEditedCB (); } @@ -159,22 +157,14 @@ void XTransProcess::adjusterChanged (Adjuster* a, double newval) void XTransProcess::methodChanged () { const int curSelection = method->get_active_row_number(); - const RAWParams::XTransSensor::Method method = RAWParams::XTransSensor::Method(curSelection); - - Glib::ustring methodName; - bool ppreq = false; - - if (curSelection >= 0 && curSelection < std::numeric_limits::max()) { - methodName = RAWParams::XTransSensor::getMethodStrings()[curSelection]; - - if (method == RAWParams::XTransSensor::Method::MONO || RAWParams::XTransSensor::Method(oldSelection) == RAWParams::XTransSensor::Method::MONO) { - ppreq = true; - } - } + const RAWParams::XTransSensor::Method currentMethod = RAWParams::XTransSensor::Method(curSelection); oldSelection = curSelection; - if (listener) { - listener->panelChanged (ppreq ? EvDemosaicMethodPreProc : EvDemosaicMethod, methodName); + if (listener && method->get_active_row_number() >= 0) { + listener->panelChanged ( + currentMethod == RAWParams::XTransSensor::Method::MONO || RAWParams::XTransSensor::Method(oldSelection) == RAWParams::XTransSensor::Method::MONO + ? EvDemosaicMethodPreProc + : EvDemosaicMethod, method->get_active_text()); } } From 51d8c76eb9fcbbf8a60b84d838348077b37d7577 Mon Sep 17 00:00:00 2001 From: heckflosse Date: Sat, 2 Jun 2018 17:22:08 +0200 Subject: [PATCH 12/42] Made own compilation uint for vng4 demosaic. Made vng4 multi-frame aware --- rtengine/CMakeLists.txt | 1 + rtengine/demosaic_algos.cc | 326 +-------------------------------- rtengine/rawimagesource.h | 2 +- rtengine/rawimagesource_i.h | 2 +- rtengine/vng4_demosaic_RT.cc | 342 +++++++++++++++++++++++++++++++++++ 5 files changed, 351 insertions(+), 322 deletions(-) create mode 100644 rtengine/vng4_demosaic_RT.cc diff --git a/rtengine/CMakeLists.txt b/rtengine/CMakeLists.txt index b12fa5e46..67b07c48c 100644 --- a/rtengine/CMakeLists.txt +++ b/rtengine/CMakeLists.txt @@ -123,6 +123,7 @@ set(RTENGINESOURCEFILES gamutwarning.cc ipshadowshighlights.cc xtrans_demosaic.cc + vng4_demosaic_RT.cc ) if(LENSFUN_HAS_LOAD_DIRECTORY) diff --git a/rtengine/demosaic_algos.cc b/rtengine/demosaic_algos.cc index d0f4eebd8..f94f6bad6 100644 --- a/rtengine/demosaic_algos.cc +++ b/rtengine/demosaic_algos.cc @@ -284,11 +284,11 @@ void RawImageSource::eahd_demosaic () // Interpolate R and B for (int i = 0; i < H; i++) { if (i == 0) { - interpolate_row_rb_mul_pp (red[i], blue[i], nullptr, green[i], green[i + 1], i, 1.0, 1.0, 1.0, 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 (red[i], blue[i], green[i - 1], green[i], nullptr, i, 1.0, 1.0, 1.0, 0, W, 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 (red[i], blue[i], green[i - 1], green[i], green[i + 1], i, 1.0, 1.0, 1.0, 0, W, 1); + 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); } } } @@ -545,11 +545,11 @@ void RawImageSource::hphd_demosaic () for (int i = 0; i < H; i++) { if (i == 0) { - interpolate_row_rb_mul_pp (red[i], blue[i], nullptr, green[i], green[i + 1], i, 1.0, 1.0, 1.0, 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 (red[i], blue[i], green[i - 1], green[i], nullptr, i, 1.0, 1.0, 1.0, 0, W, 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 (red[i], blue[i], green[i - 1], green[i], green[i + 1], i, 1.0, 1.0, 1.0, 0, W, 1); + 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); } } @@ -558,320 +558,6 @@ void RawImageSource::hphd_demosaic () } } -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -#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) -{ - const signed short int *cp, terms[] = { - -2, -2, +0, -1, 0, 0x01, -2, -2, +0, +0, 1, 0x01, -2, -1, -1, +0, 0, 0x01, - -2, -1, +0, -1, 0, 0x02, -2, -1, +0, +0, 0, 0x03, -2, -1, +0, +1, 1, 0x01, - -2, +0, +0, -1, 0, 0x06, -2, +0, +0, +0, 1, 0x02, -2, +0, +0, +1, 0, 0x03, - -2, +1, -1, +0, 0, 0x04, -2, +1, +0, -1, 1, 0x04, -2, +1, +0, +0, 0, 0x06, - -2, +1, +0, +1, 0, 0x02, -2, +2, +0, +0, 1, 0x04, -2, +2, +0, +1, 0, 0x04, - -1, -2, -1, +0, 0, 0x80, -1, -2, +0, -1, 0, 0x01, -1, -2, +1, -1, 0, 0x01, - -1, -2, +1, +0, 1, 0x01, -1, -1, -1, +1, 0, 0x88, -1, -1, +1, -2, 0, 0x40, - -1, -1, +1, -1, 0, 0x22, -1, -1, +1, +0, 0, 0x33, -1, -1, +1, +1, 1, 0x11, - -1, +0, -1, +2, 0, 0x08, -1, +0, +0, -1, 0, 0x44, -1, +0, +0, +1, 0, 0x11, - -1, +0, +1, -2, 1, 0x40, -1, +0, +1, -1, 0, 0x66, -1, +0, +1, +0, 1, 0x22, - -1, +0, +1, +1, 0, 0x33, -1, +0, +1, +2, 1, 0x10, -1, +1, +1, -1, 1, 0x44, - -1, +1, +1, +0, 0, 0x66, -1, +1, +1, +1, 0, 0x22, -1, +1, +1, +2, 0, 0x10, - -1, +2, +0, +1, 0, 0x04, -1, +2, +1, +0, 1, 0x04, -1, +2, +1, +1, 0, 0x04, - +0, -2, +0, +0, 1, 0x80, +0, -1, +0, +1, 1, 0x88, +0, -1, +1, -2, 0, 0x40, - +0, -1, +1, +0, 0, 0x11, +0, -1, +2, -2, 0, 0x40, +0, -1, +2, -1, 0, 0x20, - +0, -1, +2, +0, 0, 0x30, +0, -1, +2, +1, 1, 0x10, +0, +0, +0, +2, 1, 0x08, - +0, +0, +2, -2, 1, 0x40, +0, +0, +2, -1, 0, 0x60, +0, +0, +2, +0, 1, 0x20, - +0, +0, +2, +1, 0, 0x30, +0, +0, +2, +2, 1, 0x10, +0, +1, +1, +0, 0, 0x44, - +0, +1, +1, +2, 0, 0x10, +0, +1, +2, -1, 1, 0x40, +0, +1, +2, +0, 0, 0x60, - +0, +1, +2, +1, 0, 0x20, +0, +1, +2, +2, 0, 0x10, +1, -2, +1, +0, 0, 0x80, - +1, -1, +1, +1, 0, 0x88, +1, +0, +1, +2, 0, 0x08, +1, +0, +2, -1, 0, 0x40, - +1, +0, +2, +1, 0, 0x10 - }, - chood[] = { -1, -1, -1, 0, -1, +1, 0, +1, +1, +1, +1, 0, +1, -1, 0, -1 }; - - double progress = 0.0; - const bool plistenerActive = plistener; - - if (plistenerActive) { - plistener->setProgressStr (Glib::ustring::compose(M("TP_RAW_DMETHOD_PROGRESSBAR"), RAWParams::BayerSensor::getMethodString(RAWParams::BayerSensor::Method::VNG4))); - plistener->setProgress (progress); - } - - const unsigned prefilters = ri->prefilters; - const int width = W, height = H; - constexpr unsigned int colors = 4; - float (*image)[4]; - - image = (float (*)[4]) calloc (height * width, sizeof * image); - -#ifdef _OPENMP - #pragma omp parallel for -#endif - - for (int ii = 0; ii < H; ii++) - for (int jj = 0; jj < W; jj++) { - image[ii * W + jj][fc(ii, jj)] = rawData[ii][jj]; - } - - { - int lcode[16][16][32]; - float mul[16][16][8]; - float csum[16][16][4]; - -// first linear interpolation - for (int row = 0; row < 16; row++) - for (int col = 0; col < 16; col++) { - int * ip = lcode[row][col]; - int mulcount = 0; - float sum[4]; - memset (sum, 0, sizeof sum); - - for (int y = -1; y <= 1; y++) - for (int x = -1; x <= 1; x++) { - int shift = (y == 0) + (x == 0); - - if (shift == 2) { - continue; - } - - int color = fc(row + y, col + x); - *ip++ = (width * y + x) * 4 + color; - - mul[row][col][mulcount] = (1 << shift); - *ip++ = color; - sum[color] += (1 << shift); - mulcount++; - } - - int colcount = 0; - - for (unsigned int c = 0; c < colors; c++) - if (c != fc(row, col)) { - *ip++ = c; - csum[row][col][colcount] = sum[c]; - colcount ++; - } - } - -#ifdef _OPENMP - #pragma omp parallel for -#endif - - for (int row = 1; row < height - 1; row++) { - 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); - - 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]; - } - } - } - } - - const int prow = 7, pcol = 1; - int *code[8][2]; - int t, g; - int * ip = (int *) calloc ((prow + 1) * (pcol + 1), 1280); - - for (int row = 0; row <= prow; row++) /* Precalculate for VNG */ - for (int col = 0; col <= pcol; col++) { - code[row][col] = ip; - - for (cp = terms, t = 0; t < 64; t++) { - int y1 = *cp++; - int x1 = *cp++; - int y2 = *cp++; - int x2 = *cp++; - int weight = *cp++; - int grads = *cp++; - unsigned int color = fc(row + y1, col + x1); - - if (fc(row + y2, col + x2) != color) { - continue; - } - - int diag = (fc(row, col + 1) == color && fc(row + 1, col) == color) ? 2 : 1; - - if (abs(y1 - y2) == diag && abs(x1 - x2) == diag) { - continue; - } - - *ip++ = (y1 * width + x1) * 4 + color; - *ip++ = (y2 * width + x2) * 4 + color; - *ip++ = weight; - - for (g = 0; g < 8; g++) - if (grads & (1 << g)) { - *ip++ = g; - } - - *ip++ = -1; - } - - *ip++ = INT_MAX; - - for (cp = chood, g = 0; g < 8; g++) { - int y = *cp++; - int x = *cp++; - *ip++ = (y * width + x) * 4; - unsigned int color = fc(row, col); - - if (fc(row + y, col + x) != color && fc(row + y * 2, col + x * 2) == color) { - *ip++ = (y * width + x) * 8 + color; - } else { - *ip++ = 0; - } - } - } - - if(plistenerActive) { - progress = 0.1; - plistener->setProgress (progress); - } - - -#ifdef _OPENMP - #pragma omp parallel -#endif - { - float gval[8], thold, sum[3]; - int g; - const int progressStep = 64; - const double progressInc = (0.98 - progress) / ((height - 2) / progressStep); -#ifdef _OPENMP - #pragma omp for nowait -#endif - - for (int row = 2; row < height - 2; row++) { /* Do VNG interpolation */ - for (int col = 2; col < width - 2; col++) { - float * pix = image[row * width + col]; - int * ip = code[row & prow][col & pcol]; - memset (gval, 0, sizeof gval); - - while ((g = ip[0]) != INT_MAX) { /* Calculate gradients */ - float diff = fabsf(pix[g] - pix[ip[1]]) * (1 << ip[2]); - gval[ip[3]] += diff; - ip += 4; - - while ((g = *ip++) != -1) { - gval[g] += diff; - } - } - - ip++; - { - float gmin, gmax; - gmin = gmax = gval[0]; /* Choose a threshold */ - - for (g = 1; g < 8; g++) { - if (gmin > gval[g]) { - gmin = gval[g]; - } - - if (gmax < gval[g]) { - gmax = gval[g]; - } - } - - thold = gmin + (gmax / 2); - } - memset (sum, 0, sizeof sum); - float t1, t2; - int color = fc(row, col); - t1 = t2 = pix[color]; - - if(color & 1) { - int num = 0; - - for (g = 0; g < 8; g++, ip += 2) { /* Average the neighbors */ - if (gval[g] <= thold) { - if(ip[1]) { - sum[0] += (t1 + pix[ip[1]]) * 0.5f; - } - - sum[1] += pix[ip[0] + (color ^ 2)]; - num++; - } - } - - t1 += (sum[1] - sum[0]) / num; - } else { - int num = 0; - - for (g = 0; g < 8; g++, ip += 2) { /* Average the neighbors */ - if (gval[g] <= thold) { - sum[1] += pix[ip[0] + 1]; - sum[2] += pix[ip[0] + 3]; - - if(ip[1]) { - sum[0] += (t1 + pix[ip[1]]) * 0.5f; - } - - num++; - } - } - - t1 += (sum[1] - sum[0]) / num; - t2 += (sum[2] - sum[0]) / num; - } - - green[row][col] = 0.5f * (t1 + t2); - } - - if(plistenerActive) { - if((row % progressStep) == 0) -#ifdef _OPENMP - #pragma omp critical (updateprogress) -#endif - { - progress += progressInc; - plistener->setProgress (progress); - } - } - } - - } - free (code[0][0]); - free (image); - - if(plistenerActive) { - plistener->setProgress (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 (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 (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 (red[i], blue[i], green[i - 1], green[i], green[i + 1], i, 1.0, 1.0, 1.0, 0, W, 1); - } - } - - if(plistenerActive) { - plistener->setProgress (1.0); - } -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - #undef fc #define fc(row,col) \ (ri->get_filters() >> ((((row) << 1 & 14) + ((col) & 1)) << 1) & 3) diff --git a/rtengine/rawimagesource.h b/rtengine/rawimagesource.h index 878886fed..2672486bd 100644 --- a/rtengine/rawimagesource.h +++ b/rtengine/rawimagesource.h @@ -243,7 +243,7 @@ protected: inline void convert_to_cielab_row (float* ar, float* ag, float* ab, float* oL, float* oa, float* ob); inline void interpolate_row_g (float* agh, float* agv, int i); inline void interpolate_row_rb (float* ar, float* ab, float* pg, float* cg, float* ng, int i); - inline void interpolate_row_rb_mul_pp (float* ar, float* ab, float* pg, float* cg, float* ng, int i, float r_mul, float g_mul, float b_mul, int x1, int width, int skip); + inline void interpolate_row_rb_mul_pp (const array2D &rawData, float* ar, float* ab, float* pg, float* cg, float* ng, int i, float r_mul, float g_mul, float b_mul, int x1, int width, int skip); float* CA_correct_RT (const bool autoCA, const double cared, const double cablue, const double caautostrength, array2D &rawData, double *fitParamsTransfer, bool fitParamsIn, bool fitParamsOut, float * buffer, bool freeBuffer); void ddct8x8s(int isgn, float a[8][8]); diff --git a/rtengine/rawimagesource_i.h b/rtengine/rawimagesource_i.h index 689ab03db..91d62ecab 100644 --- a/rtengine/rawimagesource_i.h +++ b/rtengine/rawimagesource_i.h @@ -276,7 +276,7 @@ inline void RawImageSource::interpolate_row_rb (float* ar, float* ab, float* pg, } } -inline void RawImageSource::interpolate_row_rb_mul_pp (float* ar, float* ab, float* pg, float* cg, float* ng, int i, float r_mul, float g_mul, float b_mul, int x1, int width, int skip) +inline void RawImageSource::interpolate_row_rb_mul_pp (const array2D &rawData, float* ar, float* ab, float* pg, float* cg, float* ng, int i, float r_mul, float g_mul, float b_mul, int x1, int width, int skip) { if ((ri->ISRED(i, 0) || ri->ISRED(i, 1)) && pg && ng) { diff --git a/rtengine/vng4_demosaic_RT.cc b/rtengine/vng4_demosaic_RT.cc new file mode 100644 index 000000000..49c1b4f90 --- /dev/null +++ b/rtengine/vng4_demosaic_RT.cc @@ -0,0 +1,342 @@ +//////////////////////////////////////////////////////////////// +// +// VNG4 demosaic algorithm +// +// optimized for speed by Ingo Weyrich +// +// +// vng4_interpolate_RT.cc 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. +// +// This program 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 this program. If not, see . +// +//////////////////////////////////////////////////////////////// + +#include "rtengine.h" +#include "rawimagesource.h" +#include "rawimagesource_i.h" +//#include "rt_math.h" +#include "../rtgui/multilangmgr.h" +#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) +{ + BENCHFUN + const signed short int *cp, terms[] = { + -2, -2, +0, -1, 0, 0x01, -2, -2, +0, +0, 1, 0x01, -2, -1, -1, +0, 0, 0x01, + -2, -1, +0, -1, 0, 0x02, -2, -1, +0, +0, 0, 0x03, -2, -1, +0, +1, 1, 0x01, + -2, +0, +0, -1, 0, 0x06, -2, +0, +0, +0, 1, 0x02, -2, +0, +0, +1, 0, 0x03, + -2, +1, -1, +0, 0, 0x04, -2, +1, +0, -1, 1, 0x04, -2, +1, +0, +0, 0, 0x06, + -2, +1, +0, +1, 0, 0x02, -2, +2, +0, +0, 1, 0x04, -2, +2, +0, +1, 0, 0x04, + -1, -2, -1, +0, 0, 0x80, -1, -2, +0, -1, 0, 0x01, -1, -2, +1, -1, 0, 0x01, + -1, -2, +1, +0, 1, 0x01, -1, -1, -1, +1, 0, 0x88, -1, -1, +1, -2, 0, 0x40, + -1, -1, +1, -1, 0, 0x22, -1, -1, +1, +0, 0, 0x33, -1, -1, +1, +1, 1, 0x11, + -1, +0, -1, +2, 0, 0x08, -1, +0, +0, -1, 0, 0x44, -1, +0, +0, +1, 0, 0x11, + -1, +0, +1, -2, 1, 0x40, -1, +0, +1, -1, 0, 0x66, -1, +0, +1, +0, 1, 0x22, + -1, +0, +1, +1, 0, 0x33, -1, +0, +1, +2, 1, 0x10, -1, +1, +1, -1, 1, 0x44, + -1, +1, +1, +0, 0, 0x66, -1, +1, +1, +1, 0, 0x22, -1, +1, +1, +2, 0, 0x10, + -1, +2, +0, +1, 0, 0x04, -1, +2, +1, +0, 1, 0x04, -1, +2, +1, +1, 0, 0x04, + +0, -2, +0, +0, 1, 0x80, +0, -1, +0, +1, 1, 0x88, +0, -1, +1, -2, 0, 0x40, + +0, -1, +1, +0, 0, 0x11, +0, -1, +2, -2, 0, 0x40, +0, -1, +2, -1, 0, 0x20, + +0, -1, +2, +0, 0, 0x30, +0, -1, +2, +1, 1, 0x10, +0, +0, +0, +2, 1, 0x08, + +0, +0, +2, -2, 1, 0x40, +0, +0, +2, -1, 0, 0x60, +0, +0, +2, +0, 1, 0x20, + +0, +0, +2, +1, 0, 0x30, +0, +0, +2, +2, 1, 0x10, +0, +1, +1, +0, 0, 0x44, + +0, +1, +1, +2, 0, 0x10, +0, +1, +2, -1, 1, 0x40, +0, +1, +2, +0, 0, 0x60, + +0, +1, +2, +1, 0, 0x20, +0, +1, +2, +2, 0, 0x10, +1, -2, +1, +0, 0, 0x80, + +1, -1, +1, +1, 0, 0x88, +1, +0, +1, +2, 0, 0x08, +1, +0, +2, -1, 0, 0x40, + +1, +0, +2, +1, 0, 0x10 + }, + chood[] = { -1, -1, -1, 0, -1, +1, 0, +1, +1, +1, +1, 0, +1, -1, 0, -1 }; + + double progress = 0.0; + const bool plistenerActive = plistener; + + if (plistenerActive) { + plistener->setProgressStr (Glib::ustring::compose(M("TP_RAW_DMETHOD_PROGRESSBAR"), RAWParams::BayerSensor::getMethodString(RAWParams::BayerSensor::Method::VNG4))); + plistener->setProgress (progress); + } + + const unsigned prefilters = ri->prefilters; + const int width = W, height = H; + constexpr unsigned int colors = 4; + float (*image)[4]; + + image = (float (*)[4]) calloc (height * width, sizeof * image); + +#ifdef _OPENMP + #pragma omp parallel for +#endif + + for (int ii = 0; ii < H; ii++) + for (int jj = 0; jj < W; jj++) { + image[ii * W + jj][fc(ii, jj)] = rawData[ii][jj]; + } + + { + int lcode[16][16][32]; + float mul[16][16][8]; + float csum[16][16][4]; + +// first linear interpolation + for (int row = 0; row < 16; row++) + for (int col = 0; col < 16; col++) { + int * ip = lcode[row][col]; + int mulcount = 0; + float sum[4]; + memset (sum, 0, sizeof sum); + + for (int y = -1; y <= 1; y++) + for (int x = -1; x <= 1; x++) { + int shift = (y == 0) + (x == 0); + + if (shift == 2) { + continue; + } + + int color = fc(row + y, col + x); + *ip++ = (width * y + x) * 4 + color; + + mul[row][col][mulcount] = (1 << shift); + *ip++ = color; + sum[color] += (1 << shift); + mulcount++; + } + + int colcount = 0; + + for (unsigned int c = 0; c < colors; c++) + if (c != fc(row, col)) { + *ip++ = c; + csum[row][col][colcount] = sum[c]; + colcount ++; + } + } + +#ifdef _OPENMP + #pragma omp parallel for +#endif + + for (int row = 1; row < height - 1; row++) { + 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); + + 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]; + } + } + } + } + + const int prow = 7, pcol = 1; + int *code[8][2]; + int t, g; + int * ip = (int *) calloc ((prow + 1) * (pcol + 1), 1280); + + for (int row = 0; row <= prow; row++) /* Precalculate for VNG */ + for (int col = 0; col <= pcol; col++) { + code[row][col] = ip; + + for (cp = terms, t = 0; t < 64; t++) { + int y1 = *cp++; + int x1 = *cp++; + int y2 = *cp++; + int x2 = *cp++; + int weight = *cp++; + int grads = *cp++; + unsigned int color = fc(row + y1, col + x1); + + if (fc(row + y2, col + x2) != color) { + continue; + } + + int diag = (fc(row, col + 1) == color && fc(row + 1, col) == color) ? 2 : 1; + + if (abs(y1 - y2) == diag && abs(x1 - x2) == diag) { + continue; + } + + *ip++ = (y1 * width + x1) * 4 + color; + *ip++ = (y2 * width + x2) * 4 + color; + *ip++ = weight; + + for (g = 0; g < 8; g++) + if (grads & (1 << g)) { + *ip++ = g; + } + + *ip++ = -1; + } + + *ip++ = INT_MAX; + + for (cp = chood, g = 0; g < 8; g++) { + int y = *cp++; + int x = *cp++; + *ip++ = (y * width + x) * 4; + unsigned int color = fc(row, col); + + if (fc(row + y, col + x) != color && fc(row + y * 2, col + x * 2) == color) { + *ip++ = (y * width + x) * 8 + color; + } else { + *ip++ = 0; + } + } + } + + if(plistenerActive) { + progress = 0.1; + plistener->setProgress (progress); + } + + +#ifdef _OPENMP + #pragma omp parallel +#endif + { + float gval[8], thold, sum[3]; + int g; + const int progressStep = 64; + const double progressInc = (0.98 - progress) / ((height - 2) / progressStep); +#ifdef _OPENMP + #pragma omp for nowait +#endif + + for (int row = 2; row < height - 2; row++) { /* Do VNG interpolation */ + for (int col = 2; col < width - 2; col++) { + float * pix = image[row * width + col]; + int * ip = code[row & prow][col & pcol]; + memset (gval, 0, sizeof gval); + + while ((g = ip[0]) != INT_MAX) { /* Calculate gradients */ + float diff = fabsf(pix[g] - pix[ip[1]]) * (1 << ip[2]); + gval[ip[3]] += diff; + ip += 4; + + while ((g = *ip++) != -1) { + gval[g] += diff; + } + } + + ip++; + { + float gmin, gmax; + gmin = gmax = gval[0]; /* Choose a threshold */ + + for (g = 1; g < 8; g++) { + if (gmin > gval[g]) { + gmin = gval[g]; + } + + if (gmax < gval[g]) { + gmax = gval[g]; + } + } + + thold = gmin + (gmax / 2); + } + memset (sum, 0, sizeof sum); + float t1, t2; + int color = fc(row, col); + t1 = t2 = pix[color]; + + if(color & 1) { + int num = 0; + + for (g = 0; g < 8; g++, ip += 2) { /* Average the neighbors */ + if (gval[g] <= thold) { + if(ip[1]) { + sum[0] += (t1 + pix[ip[1]]) * 0.5f; + } + + sum[1] += pix[ip[0] + (color ^ 2)]; + num++; + } + } + + t1 += (sum[1] - sum[0]) / num; + } else { + int num = 0; + + for (g = 0; g < 8; g++, ip += 2) { /* Average the neighbors */ + if (gval[g] <= thold) { + sum[1] += pix[ip[0] + 1]; + sum[2] += pix[ip[0] + 3]; + + if(ip[1]) { + sum[0] += (t1 + pix[ip[1]]) * 0.5f; + } + + num++; + } + } + + t1 += (sum[1] - sum[0]) / num; + t2 += (sum[2] - sum[0]) / num; + } + + green[row][col] = 0.5f * (t1 + t2); + } + + if(plistenerActive) { + if((row % progressStep) == 0) +#ifdef _OPENMP + #pragma omp critical (updateprogress) +#endif + { + progress += progressInc; + plistener->setProgress (progress); + } + } + } + + } + free (code[0][0]); + free (image); + + if(plistenerActive) { + plistener->setProgress (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); + } + } + + if(plistenerActive) { + plistener->setProgress (1.0); + } +} +} From c3f163a323cc7cd7dce191241f9c2b6227b85372 Mon Sep 17 00:00:00 2001 From: heckflosse Date: Sun, 3 Jun 2018 16:22:34 +0200 Subject: [PATCH 13/42] Added 4-pass xtrans demosaic --- rtdata/languages/default | 1 + rtengine/expo_before_b.cc | 2 +- rtengine/procparams.cc | 5 ++ rtengine/procparams.h | 2 + rtengine/rawimagesource.cc | 4 +- rtengine/rawimagesource.h | 5 +- rtengine/vng4_demosaic_RT.cc | 144 ++++++++++++++++++----------------- rtengine/xtrans_demosaic.cc | 60 ++++++++++++++- rtgui/batchtoolpanelcoord.cc | 4 +- rtgui/paramsedited.cc | 6 ++ rtgui/paramsedited.h | 1 + rtgui/xtransprocess.cc | 43 ++++++++++- rtgui/xtransprocess.h | 5 +- 13 files changed, 203 insertions(+), 79 deletions(-) diff --git a/rtdata/languages/default b/rtdata/languages/default index 3621fc806..db3db7b5d 100644 --- a/rtdata/languages/default +++ b/rtdata/languages/default @@ -1763,6 +1763,7 @@ TP_RAWEXPOS_RGB;Red, Green, Blue TP_RAWEXPOS_TWOGREEN;Link greens TP_RAW_1PASSMEDIUM;1-Pass (Medium) TP_RAW_3PASSBEST;3-Pass (Best) +TP_RAW_4PASS;4-Pass TP_RAW_AHD;AHD TP_RAW_AMAZE;AMaZE TP_RAW_AMAZEVNG4;AMaZE+VNG4 diff --git a/rtengine/expo_before_b.cc b/rtengine/expo_before_b.cc index f94b2c292..eda8c9e37 100644 --- a/rtengine/expo_before_b.cc +++ b/rtengine/expo_before_b.cc @@ -82,7 +82,7 @@ void RawImageSource::processRawWhitepoint(float expos, float preser, array2DgetSensorType() == ST_BAYER) { fast_demosaic(); } else { - fast_xtrans_interpolate(); + fast_xtrans_interpolate(rawData, red, green, blue); } } diff --git a/rtengine/procparams.cc b/rtengine/procparams.cc index 7fc004aa0..0f364012b 100644 --- a/rtengine/procparams.cc +++ b/rtengine/procparams.cc @@ -2477,6 +2477,7 @@ Glib::ustring RAWParams::BayerSensor::getPSDemosaicMethodString(PSDemosaicMethod RAWParams::XTransSensor::XTransSensor() : method(getMethodString(Method::THREE_PASS)), + dualDemosaicContrast(20), ccSteps(0), blackred(0.0), blackgreen(0.0), @@ -2488,6 +2489,7 @@ bool RAWParams::XTransSensor::operator ==(const XTransSensor& other) const { return method == other.method + && dualDemosaicContrast == other.dualDemosaicContrast && ccSteps == other.ccSteps && blackred == other.blackred && blackgreen == other.blackgreen @@ -2502,6 +2504,7 @@ bool RAWParams::XTransSensor::operator !=(const XTransSensor& other) const const std::vector& RAWParams::XTransSensor::getMethodStrings() { static const std::vector method_strings { + "4-pass", "3-pass (best)", "1-pass (medium)", "fast", @@ -3368,6 +3371,7 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo saveToKeyfile(!pedited || pedited->raw.bayersensor.pixelShiftDemosaicMethod, "RAW Bayer", "pixelShiftDemosaicMethod", raw.bayersensor.pixelShiftDemosaicMethod, keyFile); saveToKeyfile(!pedited || pedited->raw.bayersensor.pdafLinesFilter, "RAW Bayer", "PDAFLinesFilter", raw.bayersensor.pdafLinesFilter, keyFile); saveToKeyfile(!pedited || pedited->raw.xtranssensor.method, "RAW X-Trans", "Method", raw.xtranssensor.method, keyFile); + saveToKeyfile(!pedited || pedited->raw.xtranssensor.dualDemosaicContrast, "RAW X-Trans", "DualDemosaicContrast", raw.xtranssensor.dualDemosaicContrast, keyFile); saveToKeyfile(!pedited || pedited->raw.xtranssensor.ccSteps, "RAW X-Trans", "CcSteps", raw.xtranssensor.ccSteps, keyFile); saveToKeyfile(!pedited || pedited->raw.xtranssensor.exBlackRed, "RAW X-Trans", "PreBlackRed", raw.xtranssensor.blackred, keyFile); saveToKeyfile(!pedited || pedited->raw.xtranssensor.exBlackGreen, "RAW X-Trans", "PreBlackGreen", raw.xtranssensor.blackgreen, keyFile); @@ -4724,6 +4728,7 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited) if (keyFile.has_group ("RAW X-Trans")) { assignFromKeyfile(keyFile, "RAW X-Trans", "Method", pedited, raw.xtranssensor.method, pedited->raw.xtranssensor.method); + assignFromKeyfile(keyFile, "RAW X-Trans", "DualDemosaicContrast", pedited, raw.xtranssensor.dualDemosaicContrast, pedited->raw.xtranssensor.dualDemosaicContrast); assignFromKeyfile(keyFile, "RAW X-Trans", "CcSteps", pedited, raw.xtranssensor.ccSteps, pedited->raw.xtranssensor.ccSteps); assignFromKeyfile(keyFile, "RAW X-Trans", "PreBlackRed", pedited, raw.xtranssensor.blackred, pedited->raw.xtranssensor.exBlackRed); assignFromKeyfile(keyFile, "RAW X-Trans", "PreBlackGreen", pedited, raw.xtranssensor.blackgreen, pedited->raw.xtranssensor.exBlackGreen); diff --git a/rtengine/procparams.h b/rtengine/procparams.h index 9b52cc828..48b2603c0 100644 --- a/rtengine/procparams.h +++ b/rtengine/procparams.h @@ -1307,6 +1307,7 @@ struct RAWParams { */ struct XTransSensor { enum class Method { + FOUR_PASS, THREE_PASS, ONE_PASS, FAST, @@ -1315,6 +1316,7 @@ struct RAWParams { }; Glib::ustring method; + double dualDemosaicContrast; int ccSteps; double blackred; double blackgreen; diff --git a/rtengine/rawimagesource.cc b/rtengine/rawimagesource.cc index c5af124e5..25c732947 100644 --- a/rtengine/rawimagesource.cc +++ b/rtengine/rawimagesource.cc @@ -2099,11 +2099,13 @@ void RawImageSource::demosaic(const RAWParams &raw) } else if (ri->getSensorType() == ST_FUJI_XTRANS) { if (raw.xtranssensor.method == RAWParams::XTransSensor::getMethodString(RAWParams::XTransSensor::Method::FAST) ) { - fast_xtrans_interpolate(); + fast_xtrans_interpolate(rawData, red, green, blue); } else if (raw.xtranssensor.method == RAWParams::XTransSensor::getMethodString(RAWParams::XTransSensor::Method::ONE_PASS)) { xtrans_interpolate(1, false); } else if (raw.xtranssensor.method == RAWParams::XTransSensor::getMethodString(RAWParams::XTransSensor::Method::THREE_PASS) ) { xtrans_interpolate(3, true); + } else if (raw.xtranssensor.method == RAWParams::XTransSensor::getMethodString(RAWParams::XTransSensor::Method::FOUR_PASS)) { + xtrans_4pass_demosaic_RT(3, true, raw.xtranssensor.dualDemosaicContrast); } else if(raw.xtranssensor.method == RAWParams::XTransSensor::getMethodString(RAWParams::XTransSensor::Method::MONO) ) { nodemosaic(true); } else { diff --git a/rtengine/rawimagesource.h b/rtengine/rawimagesource.h index 2672486bd..b5418d0ec 100644 --- a/rtengine/rawimagesource.h +++ b/rtengine/rawimagesource.h @@ -262,7 +262,7 @@ protected: void nodemosaic(bool bw); void eahd_demosaic(); void hphd_demosaic(); - void vng4_demosaic(const array2D &rawData, array2D &red, array2D &green, array2D &blue); + void vng4_demosaic(const array2D &rawData, array2D &red, array2D &green, array2D &blue, bool keepGreens = false); void ppg_demosaic(); void jdl_interpolate_omp(); void igv_interpolate(int winw, int winh); @@ -291,8 +291,9 @@ protected: void dcb_color_full(float (*image)[3], int x0, int y0, float (*chroma)[2]); void cielab (const float (*rgb)[3], float* l, float* a, float *b, const int width, const int height, const int labWidth, const float xyz_cam[3][3]); void xtransborder_interpolate (int border); + void xtrans_4pass_demosaic_RT (const int passes, const bool useCieLab, double contrast); void xtrans_interpolate (const int passes, const bool useCieLab); - void fast_xtrans_interpolate (); + void fast_xtrans_interpolate (const array2D &rawData, array2D &red, array2D &green, array2D &blue); void pixelshift(int winx, int winy, int winw, int winh, const RAWParams::BayerSensor &bayerParams, unsigned int frame, const std::string &make, const std::string &model, float rawWpCorrection); void hflip (Imagefloat* im); void vflip (Imagefloat* im); diff --git a/rtengine/vng4_demosaic_RT.cc b/rtengine/vng4_demosaic_RT.cc index 49c1b4f90..b996559b4 100644 --- a/rtengine/vng4_demosaic_RT.cc +++ b/rtengine/vng4_demosaic_RT.cc @@ -32,7 +32,7 @@ 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) +void RawImageSource::vng4_demosaic (const array2D &rawData, array2D &red, array2D &green, array2D &blue, bool keepGreens) { BENCHFUN const signed short int *cp, terms[] = { @@ -75,7 +75,7 @@ void RawImageSource::vng4_demosaic (const array2D &rawData, array2D &rawData, array2D &rawData, array2D &rawData, array2D &rawData, array2DsetProgress (progress); } - +StopWatch Stop3("loop3"); #ifdef _OPENMP #pragma omp parallel #endif @@ -218,83 +220,87 @@ void RawImageSource::vng4_demosaic (const array2D &rawData, array2D gval[g]) { - gmin = gval[g]; - } - - if (gmax < gval[g]) { - gmax = gval[g]; - } - } - - thold = gmin + (gmax / 2); - } - memset (sum, 0, sizeof sum); - float t1, t2; int color = fc(row, col); - t1 = t2 = pix[color]; - - if(color & 1) { - int num = 0; - - for (g = 0; g < 8; g++, ip += 2) { /* Average the neighbors */ - if (gval[g] <= thold) { - if(ip[1]) { - sum[0] += (t1 + pix[ip[1]]) * 0.5f; - } - - sum[1] += pix[ip[0] + (color ^ 2)]; - num++; - } - } - - t1 += (sum[1] - sum[0]) / num; + if (keepGreens && (color & 1)) { + green[row][col] = pix[color]; } else { - int num = 0; + int * ip = code[row & prow][col & pcol]; + memset (gval, 0, sizeof gval); - for (g = 0; g < 8; g++, ip += 2) { /* Average the neighbors */ - if (gval[g] <= thold) { - sum[1] += pix[ip[0] + 1]; - sum[2] += pix[ip[0] + 3]; + while ((g = ip[0]) != INT_MAX) { /* Calculate gradients */ + float diff = fabsf(pix[g] - pix[ip[1]]) * (1 << ip[2]); + gval[ip[3]] += diff; + ip += 4; - if(ip[1]) { - sum[0] += (t1 + pix[ip[1]]) * 0.5f; - } - - num++; + while ((g = *ip++) != -1) { + gval[g] += diff; } } - t1 += (sum[1] - sum[0]) / num; - t2 += (sum[2] - sum[0]) / num; - } + ip++; + { + float gmin, gmax; + gmin = gmax = gval[0]; /* Choose a threshold */ - green[row][col] = 0.5f * (t1 + t2); + for (g = 1; g < 8; g++) { + if (gmin > gval[g]) { + gmin = gval[g]; + } + + if (gmax < gval[g]) { + gmax = gval[g]; + } + } + + thold = gmin + (gmax / 2); + } + memset (sum, 0, sizeof sum); + float t1, t2; + t1 = t2 = pix[color]; + + if(color & 1) { + int num = 0; + + for (g = 0; g < 8; g++, ip += 2) { /* Average the neighbors */ + if (gval[g] <= thold) { + if(ip[1]) { + sum[0] += (t1 + pix[ip[1]]) * 0.5f; + } + + sum[1] += pix[ip[0] + (color ^ 2)]; + num++; + } + } + + t1 += (sum[1] - sum[0]) / num; + } else { + int num = 0; + + for (g = 0; g < 8; g++, ip += 2) { /* Average the neighbors */ + if (gval[g] <= thold) { + sum[1] += pix[ip[0] + 1]; + sum[2] += pix[ip[0] + 3]; + + if(ip[1]) { + sum[0] += (t1 + pix[ip[1]]) * 0.5f; + } + + num++; + } + } + + t1 += (sum[1] - sum[0]) / num; + t2 += (sum[2] - sum[0]) / num; + } + + green[row][col] = 0.5f * (t1 + t2); + } } if(plistenerActive) { @@ -316,7 +322,7 @@ void RawImageSource::vng4_demosaic (const array2D &rawData, array2DsetProgress (0.98); } - +Stop3.stop(); // Interpolate R and B #ifdef _OPENMP #pragma omp parallel for diff --git a/rtengine/xtrans_demosaic.cc b/rtengine/xtrans_demosaic.cc index a8e964ad0..411388ee5 100644 --- a/rtengine/xtrans_demosaic.cc +++ b/rtengine/xtrans_demosaic.cc @@ -21,6 +21,7 @@ #include "rtengine.h" #include "rawimagesource.h" +#include "rt_algo.h" #include "rt_math.h" #include "../rtgui/multilangmgr.h" #include "opthelper.h" @@ -957,7 +958,7 @@ void RawImageSource::xtrans_interpolate (const int passes, const bool useCieLab) } #undef CLIP -void RawImageSource::fast_xtrans_interpolate () +void RawImageSource::fast_xtrans_interpolate (const array2D &rawData, array2D &red, array2D &green, array2D &blue) { // if (settings->verbose) { // printf("fast X-Trans interpolation...\n"); @@ -1017,4 +1018,61 @@ void RawImageSource::fast_xtrans_interpolate () } #undef fcol #undef isgreen + +void RawImageSource::xtrans_4pass_demosaic_RT(int passes, bool useCieLab, double contrast) +{ + BENCHFUN + + if (contrast == 0.0) { + // contrast == 0.0 means only AMaZE will be used + xtrans_interpolate (passes, useCieLab); + return; + } + + xtrans_interpolate (passes, useCieLab); + + array2D redTmp(W, H); + array2D greenTmp(W, H); + array2D blueTmp(W, H); + array2D L(W, H); + + fast_xtrans_interpolate(rawData, redTmp, greenTmp, blueTmp); + const float xyz_rgb[3][3] = { // XYZ from RGB + { 0.412453, 0.357580, 0.180423 }, + { 0.212671, 0.715160, 0.072169 }, + { 0.019334, 0.119193, 0.950227 } + }; + #pragma omp parallel + { + #pragma omp for + for(int i = 0; i < H; ++i) { + Color::RGB2L(red[i], green[i], blue[i], L[i], xyz_rgb, W); + } + } + // calculate contrast based blend factors to use vng4 in regions with low contrast + JaggedArray blend(W, H); + buildBlendMask(L, blend, W, H, contrast / 100.f); + + // the following is split into 3 loops intentionally to avoid cache conflicts on CPUs with only 4-way cache + #pragma omp parallel for + for(int i = 0; i < H; ++i) { + for(int j = 0; j < W; ++j) { + red[i][j] = intp(blend[i][j], red[i][j], redTmp[i][j]); + } + } + #pragma omp parallel for + for(int i = 0; i < H; ++i) { + for(int j = 0; j < W; ++j) { + green[i][j] = intp(blend[i][j], green[i][j], greenTmp[i][j]); + } + } + #pragma omp parallel for + for(int i = 0; i < H; ++i) { + for(int j = 0; j < W; ++j) { + blue[i][j] = intp(blend[i][j], blue[i][j], blueTmp[i][j]); + } + } + +} + } \ No newline at end of file diff --git a/rtgui/batchtoolpanelcoord.cc b/rtgui/batchtoolpanelcoord.cc index 81f61471e..fb92bbde0 100644 --- a/rtgui/batchtoolpanelcoord.cc +++ b/rtgui/batchtoolpanelcoord.cc @@ -165,7 +165,7 @@ void BatchToolPanelCoordinator::initSession () wavelet->setAdjusterBehavior (false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false); dirpyrdenoise->setAdjusterBehavior (false, false, false, false, false, false, false); bayerprocess->setAdjusterBehavior(false, false, false, false, false, false); - xtransprocess->setAdjusterBehavior(false); + xtransprocess->setAdjusterBehavior(false, false); bayerpreprocess->setAdjusterBehavior (false, false); rawcacorrection->setAdjusterBehavior (false); flatfield->setAdjusterBehavior(false); @@ -212,7 +212,7 @@ void BatchToolPanelCoordinator::initSession () wavelet->setAdjusterBehavior (options.baBehav[ADDSET_WA], options.baBehav[ADDSET_WA_THRESHOLD], options.baBehav[ADDSET_WA_THRESHOLD2], options.baBehav[ADDSET_WA_THRES], options.baBehav[ADDSET_WA_CHRO], options.baBehav[ADDSET_WA_CHROMA], options.baBehav[ADDSET_WA_CONTRAST], options.baBehav[ADDSET_WA_SKINPROTECT], options.baBehav[ADDSET_WA_RESCHRO], options.baBehav[ADDSET_WA_TMRS], options.baBehav[ADDSET_WA_RESCON], options.baBehav[ADDSET_WA_RESCONH], options.baBehav[ADDSET_WA_THRR], options.baBehav[ADDSET_WA_THRRH], options.baBehav[ADDSET_WA_SKYPROTECT], options.baBehav[ADDSET_WA_EDGRAD], options.baBehav[ADDSET_WA_EDGVAL], options.baBehav[ADDSET_WA_STRENGTH], options.baBehav[ADDSET_WA_GAMMA], options.baBehav[ADDSET_WA_EDGEDETECT], options.baBehav[ADDSET_WA_EDGEDETECTTHR], options.baBehav[ADDSET_WA_EDGEDETECTTHR2]); dirpyrdenoise->setAdjusterBehavior (options.baBehav[ADDSET_DIRPYRDN_LUMA], options.baBehav[ADDSET_DIRPYRDN_LUMDET], options.baBehav[ADDSET_DIRPYRDN_CHROMA], options.baBehav[ADDSET_DIRPYRDN_CHROMARED], options.baBehav[ADDSET_DIRPYRDN_CHROMABLUE], options.baBehav[ADDSET_DIRPYRDN_GAMMA], options.baBehav[ADDSET_DIRPYRDN_PASSES]); bayerprocess->setAdjusterBehavior(options.baBehav[ADDSET_BAYER_FALSE_COLOR_SUPPRESSION], options.baBehav[ADDSET_BAYER_ITER], options.baBehav[ADDSET_BAYER_DUALDEMOZCONTRAST], options.baBehav[ADDSET_BAYER_PS_SIGMA], options.baBehav[ADDSET_BAYER_PS_SMOOTH], options.baBehav[ADDSET_BAYER_PS_EPERISO]); - xtransprocess->setAdjusterBehavior(options.baBehav[ADDSET_BAYER_FALSE_COLOR_SUPPRESSION]); + xtransprocess->setAdjusterBehavior(options.baBehav[ADDSET_BAYER_FALSE_COLOR_SUPPRESSION], options.baBehav[ADDSET_BAYER_DUALDEMOZCONTRAST]); bayerpreprocess->setAdjusterBehavior (options.baBehav[ADDSET_PREPROCESS_LINEDENOISE], options.baBehav[ADDSET_PREPROCESS_GREENEQUIL]); rawcacorrection->setAdjusterBehavior (options.baBehav[ADDSET_RAWCACORR]); flatfield->setAdjusterBehavior(options.baBehav[ADDSET_RAWFFCLIPCONTROL]); diff --git a/rtgui/paramsedited.cc b/rtgui/paramsedited.cc index 9e6d3b6e7..d14635d10 100644 --- a/rtgui/paramsedited.cc +++ b/rtgui/paramsedited.cc @@ -423,6 +423,7 @@ void ParamsEdited::set (bool v) raw.bayersensor.linenoiseDirection = v; raw.bayersensor.pdafLinesFilter = v; raw.xtranssensor.method = v; + raw.xtranssensor.dualDemosaicContrast = v; raw.xtranssensor.ccSteps = v; raw.xtranssensor.exBlackRed = v; raw.xtranssensor.exBlackGreen = v; @@ -973,6 +974,7 @@ void ParamsEdited::initFrom (const std::vector raw.bayersensor.linenoiseDirection = raw.bayersensor.linenoiseDirection && p.raw.bayersensor.linenoiseDirection == other.raw.bayersensor.linenoiseDirection; raw.bayersensor.pdafLinesFilter = raw.bayersensor.pdafLinesFilter && p.raw.bayersensor.pdafLinesFilter == other.raw.bayersensor.pdafLinesFilter; raw.xtranssensor.method = raw.xtranssensor.method && p.raw.xtranssensor.method == other.raw.xtranssensor.method; + raw.xtranssensor.dualDemosaicContrast = raw.xtranssensor.dualDemosaicContrast && p.raw.xtranssensor.dualDemosaicContrast == other.raw.xtranssensor.dualDemosaicContrast; raw.xtranssensor.ccSteps = raw.xtranssensor.ccSteps && p.raw.xtranssensor.ccSteps == other.raw.xtranssensor.ccSteps; raw.xtranssensor.exBlackRed = raw.xtranssensor.exBlackRed && p.raw.xtranssensor.blackred == other.raw.xtranssensor.blackred; raw.xtranssensor.exBlackGreen = raw.xtranssensor.exBlackGreen && p.raw.xtranssensor.blackgreen == other.raw.xtranssensor.blackgreen; @@ -2578,6 +2580,10 @@ void ParamsEdited::combine (rtengine::procparams::ProcParams& toEdit, const rten toEdit.raw.xtranssensor.method = mods.raw.xtranssensor.method; } + if (raw.xtranssensor.dualDemosaicContrast) { + toEdit.raw.xtranssensor.dualDemosaicContrast = mods.raw.xtranssensor.dualDemosaicContrast; + } + if (raw.xtranssensor.ccSteps) { toEdit.raw.xtranssensor.ccSteps = mods.raw.xtranssensor.ccSteps; } diff --git a/rtgui/paramsedited.h b/rtgui/paramsedited.h index 1db298dfd..546a5c333 100644 --- a/rtgui/paramsedited.h +++ b/rtgui/paramsedited.h @@ -761,6 +761,7 @@ public: public: bool method; + bool dualDemosaicContrast; bool ccSteps; bool exBlackRed; bool exBlackGreen; diff --git a/rtgui/xtransprocess.cc b/rtgui/xtransprocess.cc index 456a7c4d5..334f0d0d9 100644 --- a/rtgui/xtransprocess.cc +++ b/rtgui/xtransprocess.cc @@ -16,6 +16,7 @@ * You should have received a copy of the GNU General Public License * along with RawTherapee. If not, see . */ +#include "eventmapper.h" #include "xtransprocess.h" #include "options.h" #include "guiutils.h" @@ -25,6 +26,9 @@ using namespace rtengine::procparams; XTransProcess::XTransProcess () : FoldableToolPanel(this, "xtransprocess", M("TP_RAW_LABEL"), true) { + auto m = ProcEventMapper::getInstance(); + EvDemosaicContrast = m->newEvent(DEMOSAIC, "HISTORY_MSG_DUALDEMOSAIC_CONTRAST"); + Gtk::HBox* hb1 = Gtk::manage (new Gtk::HBox ()); hb1->pack_start (*Gtk::manage (new Gtk::Label ( M("TP_RAW_DMETHOD") + ": ")), Gtk::PACK_SHRINK, 4); method = Gtk::manage (new MyComboBoxText ()); @@ -63,6 +67,20 @@ XTransProcess::XTransProcess () : FoldableToolPanel(this, "xtransprocess", M("TP hb1->pack_end (*method, Gtk::PACK_EXPAND_WIDGET, 4); pack_start( *hb1, Gtk::PACK_SHRINK, 4); + dualDemosaicOptions = Gtk::manage (new Gtk::VBox ()); + + dualDemosaicContrast = Gtk::manage(new Adjuster (M("TP_RAW_DUALDEMOSAICCONTRAST"), 0, 200, 1, 20)); + dualDemosaicContrast->setAdjusterListener (this); +// dualDemosaicContrast->set_tooltip_markup (M("TP_RAW_LMMSE_TOOLTIP")); + + if (dualDemosaicContrast->delay < options.adjusterMaxDelay) { + dualDemosaicContrast->delay = options.adjusterMaxDelay; + } + + dualDemosaicContrast->show(); + dualDemosaicOptions->pack_start(*dualDemosaicContrast); + pack_start( *dualDemosaicOptions, Gtk::PACK_SHRINK, 4); + pack_start( *Gtk::manage( new Gtk::HSeparator()), Gtk::PACK_SHRINK, 0 ); ccSteps = Gtk::manage (new Adjuster (M("TP_RAW_FALSECOLOR"), 0, 5, 1, 0 )); ccSteps->setAdjusterListener (this); @@ -91,14 +109,18 @@ void XTransProcess::read(const rtengine::procparams::ProcParams* pp, const Param } if(pedited ) { + dualDemosaicContrast->setEditedState ( pedited->raw.xtranssensor.dualDemosaicContrast ? Edited : UnEdited); ccSteps->setEditedState (pedited->raw.xtranssensor.ccSteps ? Edited : UnEdited); if( !pedited->raw.xtranssensor.method ) { method->set_active_text(M("GENERAL_UNCHANGED")); } } - + dualDemosaicContrast->setValue (pp->raw.xtranssensor.dualDemosaicContrast); ccSteps->setValue (pp->raw.xtranssensor.ccSteps); + if (!batchMode) { + dualDemosaicOptions->set_visible(pp->raw.xtranssensor.method == procparams::RAWParams::XTransSensor::getMethodString(procparams::RAWParams::XTransSensor::Method::FOUR_PASS)); + } methodconn.block (false); @@ -107,6 +129,7 @@ void XTransProcess::read(const rtengine::procparams::ProcParams* pp, const Param void XTransProcess::write( rtengine::procparams::ProcParams* pp, ParamsEdited* pedited) { + pp->raw.xtranssensor.dualDemosaicContrast = dualDemosaicContrast->getValue(); pp->raw.xtranssensor.ccSteps = ccSteps->getIntValue(); int currentRow = method->get_active_row_number(); @@ -117,12 +140,14 @@ void XTransProcess::write( rtengine::procparams::ProcParams* pp, ParamsEdited* p if (pedited) { pedited->raw.xtranssensor.method = method->get_active_text() != M("GENERAL_UNCHANGED"); + pedited->raw.xtranssensor.dualDemosaicContrast = dualDemosaicContrast->getEditedState (); pedited->raw.xtranssensor.ccSteps = ccSteps->getEditedState (); } } -void XTransProcess::setAdjusterBehavior (bool falsecoloradd) +void XTransProcess::setAdjusterBehavior (bool falsecoloradd, bool dualDemosaicContrastAdd) { + dualDemosaicContrast->setAddMode(dualDemosaicContrastAdd); ccSteps->setAddMode(falsecoloradd); } @@ -131,16 +156,20 @@ void XTransProcess::setBatchMode(bool batchMode) method->append (M("GENERAL_UNCHANGED")); method->set_active_text(M("GENERAL_UNCHANGED")); ToolPanel::setBatchMode (batchMode); + dualDemosaicContrast->showEditedCB (); ccSteps->showEditedCB (); } void XTransProcess::setDefaults(const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited) { + dualDemosaicContrast->setDefault( defParams->raw.xtranssensor.dualDemosaicContrast); ccSteps->setDefault (defParams->raw.xtranssensor.ccSteps); if (pedited) { + dualDemosaicContrast->setDefaultEditedState( pedited->raw.xtranssensor.dualDemosaicContrast ? Edited : UnEdited); ccSteps->setDefaultEditedState(pedited->raw.xtranssensor.ccSteps ? Edited : UnEdited); } else { + dualDemosaicContrast->setDefaultEditedState(Irrelevant ); ccSteps->setDefaultEditedState(Irrelevant ); } } @@ -150,6 +179,8 @@ void XTransProcess::adjusterChanged (Adjuster* a, double newval) if (listener) { if (a == ccSteps) { listener->panelChanged (EvDemosaicFalseColorIter, a->getTextValue() ); + } else if (a == dualDemosaicContrast) { + listener->panelChanged (EvDemosaicContrast, a->getTextValue() ); } } } @@ -161,6 +192,14 @@ void XTransProcess::methodChanged () oldSelection = curSelection; + if (!batchMode) { + if (currentMethod == procparams::RAWParams::XTransSensor::Method::FOUR_PASS) { + dualDemosaicOptions->show(); + } else { + dualDemosaicOptions->hide(); + } + + } if (listener && method->get_active_row_number() >= 0) { listener->panelChanged ( currentMethod == RAWParams::XTransSensor::Method::MONO || RAWParams::XTransSensor::Method(oldSelection) == RAWParams::XTransSensor::Method::MONO diff --git a/rtgui/xtransprocess.h b/rtgui/xtransprocess.h index 274b52c29..edc0965b8 100644 --- a/rtgui/xtransprocess.h +++ b/rtgui/xtransprocess.h @@ -32,9 +32,12 @@ protected: MyComboBoxText* method; Adjuster* ccSteps; + Gtk::VBox *dualDemosaicOptions; + Adjuster* dualDemosaicContrast; int oldSelection; sigc::connection methodconn; + rtengine::ProcEvent EvDemosaicContrast; public: @@ -42,7 +45,7 @@ public: void read(const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited = nullptr); void write(rtengine::procparams::ProcParams* pp, ParamsEdited* pedited = nullptr); - void setAdjusterBehavior(bool falsecoloradd); + void setAdjusterBehavior(bool falsecoloradd, bool dualDemosaicContrastAdd); void setBatchMode(bool batchMode); void setDefaults(const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited = nullptr); From 5101e1d4e7f14f0c16bd9ce1c363a50fdd79f313 Mon Sep 17 00:00:00 2001 From: heckflosse Date: Mon, 4 Jun 2018 16:09:49 +0200 Subject: [PATCH 14/42] Changed order of bayer demosaicers in combobox --- rtengine/procparams.cc | 12 ++++++------ rtengine/procparams.h | 12 ++++++------ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/rtengine/procparams.cc b/rtengine/procparams.cc index 0f364012b..9f6f26cf5 100644 --- a/rtengine/procparams.cc +++ b/rtengine/procparams.cc @@ -2436,19 +2436,19 @@ const std::vector& RAWParams::BayerSensor::getMethodStrings() { static const std::vector method_strings { "amaze", - "igv", + "amazevng4", + "rcd", + "dcb", "lmmse", + "igv", + "ahd", "eahd", "hphd", "vng4", - "dcb", - "ahd", - "rcd", "fast", "mono", - "none", "pixelshift", - "amazevng4" + "none" }; return method_strings; } diff --git a/rtengine/procparams.h b/rtengine/procparams.h index 48b2603c0..121fb8afa 100644 --- a/rtengine/procparams.h +++ b/rtengine/procparams.h @@ -1224,19 +1224,19 @@ struct RAWParams { struct BayerSensor { enum class Method { AMAZE, - IGV, + AMAZEVNG4, + RCD, + DCB, LMMSE, + IGV, + AHD, EAHD, HPHD, VNG4, - DCB, - AHD, - RCD, FAST, MONO, - NONE, PIXELSHIFT, - AMAZEVNG4 + NONE }; enum class PSMotionCorrectionMethod { From d03907bcf89756e9fcd4a35bfc2ab8ffb55fab10 Mon Sep 17 00:00:00 2001 From: heckflosse Date: Tue, 5 Jun 2018 15:09:32 +0200 Subject: [PATCH 15/42] Strange color artifacts in Jupiter, fixes #4587 --- rtengine/green_equil_RT.cc | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/rtengine/green_equil_RT.cc b/rtengine/green_equil_RT.cc index 934b7df4a..9706b06c1 100644 --- a/rtengine/green_equil_RT.cc +++ b/rtengine/green_equil_RT.cc @@ -46,13 +46,14 @@ void RawImageSource::green_equilibrate_global(array2D &rawData) for (int i = border; i < H - border; i++) { double avgg = 0.; - + int ng = 0; for (int j = border + ((FC(i, border) & 1) ^ 1); j < W - border; j += 2) { - avgg += rawData[i][j]; + if(rawData[i][j] > 0.f) { + avgg += rawData[i][j]; + ng++; + } } - int ng = (W - 2 * border + (FC(i, border) & 1)) / 2; - if (i & 1) { avgg2 += avgg; ng2 += ng; From a7e783a3cfda2bc4ff6e9ef8b9a2803491a8ffa8 Mon Sep 17 00:00:00 2001 From: heckflosse Date: Tue, 5 Jun 2018 15:48:10 +0200 Subject: [PATCH 16/42] Fix bug in BayerProcess::methodChanged () --- rtgui/bayerprocess.cc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/rtgui/bayerprocess.cc b/rtgui/bayerprocess.cc index 72fa4c42f..26475bc90 100644 --- a/rtgui/bayerprocess.cc +++ b/rtgui/bayerprocess.cc @@ -549,14 +549,15 @@ void BayerProcess::methodChanged () } } - oldMethod = currentSelection; - if (listener && method->get_active_row_number() >= 0) { listener->panelChanged ( currentMethod == procparams::RAWParams::BayerSensor::Method::MONO || RAWParams::BayerSensor::Method(oldMethod) == procparams::RAWParams::BayerSensor::Method::MONO ? EvDemosaicMethodPreProc : EvDemosaicMethod, method->get_active_text()); } + + oldMethod = currentSelection; + } void BayerProcess::pixelShiftDemosaicMethodChanged () From e542a38f8536a77687213c612c933c026fef3248 Mon Sep 17 00:00:00 2001 From: heckflosse Date: Tue, 5 Jun 2018 18:51:07 +0200 Subject: [PATCH 17/42] Revert latest commit (kind of) and disable automatic global green equilibration for OLYMPUS E-M1MarkII --- rtengine/green_equil_RT.cc | 4 ++-- rtengine/rawimagesource.cc | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/rtengine/green_equil_RT.cc b/rtengine/green_equil_RT.cc index 9706b06c1..77365dc21 100644 --- a/rtengine/green_equil_RT.cc +++ b/rtengine/green_equil_RT.cc @@ -48,10 +48,10 @@ void RawImageSource::green_equilibrate_global(array2D &rawData) double avgg = 0.; int ng = 0; for (int j = border + ((FC(i, border) & 1) ^ 1); j < W - border; j += 2) { - if(rawData[i][j] > 0.f) { +// if(rawData[i][j] > 0.f) { avgg += rawData[i][j]; ng++; - } +// } } if (i & 1) { diff --git a/rtengine/rawimagesource.cc b/rtengine/rawimagesource.cc index 25c732947..5d654317c 100644 --- a/rtengine/rawimagesource.cc +++ b/rtengine/rawimagesource.cc @@ -1952,7 +1952,7 @@ void RawImageSource::preprocess (const RAWParams &raw, const LensProfParams &le for(int i = 0; i < 4; ++i) { green_equilibrate_global(*rawDataFrames[i]); } - } else { + } else if(idata->getModel() != "E-M1MarkII") { green_equilibrate_global(rawData); } } From 9889f878aaa32c38e7b1578fbd770340653a9ed7 Mon Sep 17 00:00:00 2001 From: heckflosse Date: Thu, 7 Jun 2018 15:44:52 +0200 Subject: [PATCH 18/42] Spot white balance sometimes failes, fixes #4589 --- rtengine/rawimagesource.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/rtengine/rawimagesource.cc b/rtengine/rawimagesource.cc index 6f119a2ad..cdb554622 100644 --- a/rtengine/rawimagesource.cc +++ b/rtengine/rawimagesource.cc @@ -5212,7 +5212,7 @@ ColorTemp RawImageSource::getSpotWB (std::vector &red, std::vector &red, std::vector &red, std::vector Date: Thu, 7 Jun 2018 16:01:01 +0200 Subject: [PATCH 19/42] Fixed SpotWb also for xtrans, #4589 --- rtengine/rawimagesource.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rtengine/rawimagesource.cc b/rtengine/rawimagesource.cc index cdb554622..1622d65a1 100644 --- a/rtengine/rawimagesource.cc +++ b/rtengine/rawimagesource.cc @@ -5139,7 +5139,7 @@ ColorTemp RawImageSource::getSpotWB (std::vector &red, std::vector Date: Thu, 7 Jun 2018 18:01:37 +0200 Subject: [PATCH 20/42] Exclude very dark regions from calculation of pre demosaic auto white balance, #4587 --- rtengine/rawimage.cc | 39 +++++++++++++-------------------------- 1 file changed, 13 insertions(+), 26 deletions(-) diff --git a/rtengine/rawimage.cc b/rtengine/rawimage.cc index 1e8cb02ad..6ef110a03 100644 --- a/rtengine/rawimage.cc +++ b/rtengine/rawimage.cc @@ -118,6 +118,8 @@ void RawImage::get_colorsCoeff( float *pre_mul_, float *scale_mul_, float *cblac } memset(dsum, 0, sizeof dsum); + constexpr float blackThreshold = 8.f; + constexpr float whiteThreshold = 25.f; if (this->isBayer()) { // calculate number of pixels per color dsum[FC(0, 0) + 4] += (int)(((W + 1) / 2) * ((H + 1) / 2)); @@ -135,8 +137,8 @@ void RawImage::get_colorsCoeff( float *pre_mul_, float *scale_mul_, float *cblac float whitefloat[4]; for (int c = 0; c < 4; c++) { - cblackfloat[c] = cblack_[c]; - whitefloat[c] = this->get_white(c) - 25; + cblackfloat[c] = cblack_[c] + blackThreshold; + whitefloat[c] = this->get_white(c) - whiteThreshold; } float *tempdata = data[0]; @@ -154,7 +156,7 @@ void RawImage::get_colorsCoeff( float *pre_mul_, float *scale_mul_, float *cblac int c = FC(y, x); val = tempdata[y * W + x]; - if (val > whitefloat[c]) { // calculate number of pixels to be substracted from sum and skip the block + if (val > whitefloat[c] || val < cblackfloat[c]) { // calculate number of pixels to be subtracted from sum and skip the block dsumthr[FC(row, col) + 4] += (int)(((xmax - col + 1) / 2) * ((ymax - row + 1) / 2)); dsumthr[FC(row, col + 1) + 4] += (int)(((xmax - col) / 2) * ((ymax - row + 1) / 2)); dsumthr[FC(row + 1, col) + 4] += (int)(((xmax - col + 1) / 2) * ((ymax - row) / 2)); @@ -162,10 +164,6 @@ void RawImage::get_colorsCoeff( float *pre_mul_, float *scale_mul_, float *cblac goto skip_block2; } - if (val < cblackfloat[c]) { - val = cblackfloat[c]; - } - sum[c] += val; } @@ -202,11 +200,13 @@ skip_block2: memset(dsumthr, 0, sizeof dsumthr); float sum[8]; // make local copies of the black and white values to avoid calculations and conversions + float cblackfloat[4]; float whitefloat[4]; for (int c = 0; c < 4; c++) { - whitefloat[c] = this->get_white(c) - 25; + cblackfloat[c] = cblack_[c] + blackThreshold; + whitefloat[c] = this->get_white(c) - whiteThreshold; } #pragma omp for nowait @@ -221,13 +221,11 @@ skip_block2: int c = XTRANSFC(y, x); float val = data[y][x]; - if (val > whitefloat[c]) { + if (val > whitefloat[c] || val < cblackfloat[c]) { goto skip_block3; } - if ((val -= cblack_[c]) < 0) { - val = 0; - } + val -= cblack_[c]; sum[c] += val; sum[c + 4]++; @@ -262,27 +260,16 @@ skip_block3: for (size_t y = row; y < row + 8 && y < H; y++) for (size_t x = col; x < col + 8 && x < W; x++) for (int c = 0; c < 3; c++) { - if (this->isBayer()) { - c = FC(y, x); - val = data[y][x]; - } else { - val = data[y][3 * x + c]; - } + val = data[y][3 * x + c]; - if (val > this->get_white(c) - 25) { + if (val > this->get_white(c) - whiteThreshold || val < cblack_[c] + blackThreshold) { goto skip_block; } - if ((val -= cblack_[c]) < 0) { - val = 0; - } + val -= cblack_[c]; sum[c] += val; sum[c + 4]++; - - if ( this->isBayer()) { - break; - } } for (c = 0; c < 8; c++) { From 6a9cb147e7eae45238b470ce01a457ba044cfd29 Mon Sep 17 00:00:00 2001 From: TooWaBoo Date: Thu, 7 Jun 2018 18:08:01 +0200 Subject: [PATCH 21/42] Update Deutsch locale --- rtdata/languages/Deutsch | 42 ++++++++++++++++++++-------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/rtdata/languages/Deutsch b/rtdata/languages/Deutsch index 993206ed3..75aa4a42a 100644 --- a/rtdata/languages/Deutsch +++ b/rtdata/languages/Deutsch @@ -463,11 +463,11 @@ HISTORY_MSG_154;(Dynamik)\nHautfarbtöne schützen HISTORY_MSG_155;(Dynamik)\nFarbverschiebungen\nvermeiden HISTORY_MSG_156;(Dynamik)\nPastell und gesättigte\nTöne koppeln HISTORY_MSG_157;(Dynamik)\nPastell/gesättigte Töne\nSchwelle -HISTORY_MSG_158;(Dynamikkompression)\nIntensität -HISTORY_MSG_159;(Dynamikkompression)\nKantenschutz -HISTORY_MSG_160;(Dynamikkompression)\nFaktor -HISTORY_MSG_161;(Dynamikkompression)\nIterationen -HISTORY_MSG_162;(Dynamikkompression) +HISTORY_MSG_158;(Tonwertkorrektur)\nIntensität +HISTORY_MSG_159;(Tonwertkorrektur)\nKantenschutz +HISTORY_MSG_160;(Tonwertkorrektur)\nFaktor +HISTORY_MSG_161;(Tonwertkorrektur)\nIterationen +HISTORY_MSG_162;(Tonwertkorrektur) HISTORY_MSG_163;(RGB-Kurven) - Rot HISTORY_MSG_164;(RGB-Kurven) - Grün HISTORY_MSG_165;(RGB-Kurven) - Blau @@ -664,7 +664,7 @@ HISTORY_MSG_356;(Wavelet)\nKantenschärfung\nSchwelle hoch HISTORY_MSG_357;(Wavelet)\nRauschreduzierung\nSchärfung verknüpfen HISTORY_MSG_358;(Wavelet) - Gamut\nKontrastkurve HISTORY_MSG_359;(Vorverarbeitung)\nHot / Dead-Pixel-Filter\nSchwelle -HISTORY_MSG_360;(Dynamikkompression)\nGamma +HISTORY_MSG_360;(Tonwertkorrektur)\nGamma HISTORY_MSG_361;(Wavelet) - Endretusche\nFarbausgleich HISTORY_MSG_362;(Wavelet) - Restbild\nKompression HISTORY_MSG_363;(Wavelet) - Restbild\nKompression - Intensität @@ -955,7 +955,7 @@ PARTIALPASTE_DIALOGLABEL;Selektives Einfügen des Bearbeitungsprofils PARTIALPASTE_DIRPYRDENOISE;Rauschreduzierung PARTIALPASTE_DIRPYREQUALIZER;Detailebenenkontrast PARTIALPASTE_DISTORTION;Verzeichnungskorrektur -PARTIALPASTE_EPD;Dynamikkompression +PARTIALPASTE_EPD;Tonwertkorrektur PARTIALPASTE_EQUALIZER;Anzahl der Ebenen PARTIALPASTE_EVERYTHING;Alle Parameter aktivieren / deaktivieren PARTIALPASTE_EXIFCHANGES;Änderungen an Exif-Daten @@ -1460,8 +1460,8 @@ TP_COLORAPP_TCMODE_LABEL3;Farbkurve Modus TP_COLORAPP_TCMODE_LIGHTNESS;Helligkeit (J) TP_COLORAPP_TCMODE_SATUR;Sättigung (S) TP_COLORAPP_TEMP_TOOLTIP;Um eine Farbtemperatur auszuwählen\nsetzen Sie die Tönung immer auf "1".\nA Temp=2856\nD50 Temp=5003\nD55 Temp=5503\nD65 Temp=6504\nD75 Temp=7504 -TP_COLORAPP_TONECIE;Dynamikkompression mittels\nCIECAM02-Helligkeit (Q) -TP_COLORAPP_TONECIE_TOOLTIP;Wenn diese Option ausgeschaltet ist, wird die Dynamikkompression im L*a*b*-Farbraum durchgeführt.\nWenn die Option eingeschaltet ist, wird CIECAM02 für die Dynamikkompression verwendet. Das Werkzeug Dynamikkompression muss aktiviert sein, damit diese Option berücksichtigt wird. +TP_COLORAPP_TONECIE;Tonwertkorrektur mittels\nCIECAM02-Helligkeit (Q) +TP_COLORAPP_TONECIE_TOOLTIP;Wenn diese Option ausgeschaltet ist, wird die Tonwertkorrektur im L*a*b*-Farbraum durchgeführt.\nWenn die Option eingeschaltet ist, wird CIECAM02 für die Tonwertkorrektur verwendet. Das Werkzeug Tonwertkorrektur muss aktiviert sein, damit diese Option berücksichtigt wird. TP_COLORAPP_WBCAM;[RT+CAT02] + [Ausgabe] TP_COLORAPP_WBRT;[RT] + [Ausgabe] TP_COLORAPP_YB;Yb% (Ø Luminanz) @@ -1606,11 +1606,11 @@ TP_DISTORTION_AUTO_TIP;Korrigiert die Verzeichnung in RAW-Bildern durch Vergleic TP_DISTORTION_LABEL;Verzeichnungskorrektur TP_EPD_EDGESTOPPING;Kantenschutz TP_EPD_GAMMA;Gamma -TP_EPD_LABEL;Dynamikkompression +TP_EPD_LABEL;Tonwertkorrektur TP_EPD_REWEIGHTINGITERATES;Iterationen TP_EPD_SCALE;Faktor TP_EPD_STRENGTH;Intensität -TP_EPD_TOOLTIP;Dynamikkompression ist mit dem L*a*b*- und CIECAM02-Modus möglich.\n\nFür den CIECAM02-Modus müssen folgende Optionen aktiviert sein:\n1. CIECAM02\n2. Algorithmus = Helligkeit + Farbigkeit (QM)\n3. Dynamikkompression mittels CIECAM02-Helligkeit (Q) +TP_EPD_TOOLTIP;Tonwertkorrektur ist mit dem L*a*b*- und CIECAM02-Modus möglich.\n\nFür den CIECAM02-Modus müssen folgende Optionen aktiviert sein:\n1. CIECAM02\n2. Algorithmus = Helligkeit + Farbigkeit (QM)\n3. Tonwertkorrektur mittels CIECAM02-Helligkeit (Q) TP_EXPOSURE_AUTOLEVELS;Auto TP_EXPOSURE_AUTOLEVELS_TIP;Automatische Belichtungseinstellung\nbasierend auf Bildanalyse. TP_EXPOSURE_BLACKLEVEL;Schwarzwert @@ -2221,7 +2221,7 @@ TP_WAVELET_TILESIZE;Kachelgröße TP_WAVELET_TILESLIT;Kleine Kacheln TP_WAVELET_TILES_TOOLTIP;“Ganzes Bild“ (empfohlen) liefert eine bessere Qualität.\n“Kacheln“ benötigen weniger Speicher und ist nur für\nComputer mit wenig RAM zu empfehlen. TP_WAVELET_TMSTRENGTH;Intensität -TP_WAVELET_TMSTRENGTH_TOOLTIP;Kontrolliert die Intensität der Dynamik- oder\nKontrastkompression des Restbildes. Ist der\nWert ungleich 0, werden die Intensitäts- und\nGammaregler des Dynamikkompressions-\nWerkzeugs im Belichtungsreiter deaktiviert. +TP_WAVELET_TMSTRENGTH_TOOLTIP;Kontrolliert die Intensität der Dynamik- oder\nKontrastkompression des Restbildes. Ist der\nWert ungleich 0, werden die Intensitäts- und\nGammaregler des Tonwertkorrektur-\nWerkzeugs im Belichtungsreiter deaktiviert. TP_WAVELET_TMTYPE;Kompression TP_WAVELET_TON;Tönung TP_WBALANCE_AUTO;Automatisch @@ -2284,12 +2284,12 @@ ZOOMPANEL_ZOOMOUT;Herauszoomen\nTaste: - ! Untranslated keys follow; remove the ! prefix after an entry is translated. !!!!!!!!!!!!!!!!!!!!!!!!! -!HISTORY_MSG_488;Dynamic Range Compression -!HISTORY_MSG_489;DRC - Threshold -!HISTORY_MSG_490;DRC - Amount -!HISTORY_MSG_TM_FATTAL_ANCHOR;DRC - Anchor -!PARTIALPASTE_TM_FATTAL;Dynamic Range Compression -!TP_TM_FATTAL_AMOUNT;Amount -!TP_TM_FATTAL_ANCHOR;Anchor -!TP_TM_FATTAL_LABEL;Dynamic Range Compression -!TP_TM_FATTAL_THRESHOLD;Threshold +HISTORY_MSG_488;(Dynamikkompression) +HISTORY_MSG_489;(Dynamikkompression)\nSchwelle +HISTORY_MSG_490;(Dynamikkompression)\nIntensität +HISTORY_MSG_TM_FATTAL_ANCHOR;(Dynamikkompression)\nHelligkeitsverschiebung +PARTIALPASTE_TM_FATTAL;Dynamikkompression +TP_TM_FATTAL_AMOUNT;Intensität +TP_TM_FATTAL_ANCHOR;Helligkeitsverschiebung +TP_TM_FATTAL_LABEL;Dynamikkompression +TP_TM_FATTAL_THRESHOLD;Schwelle From d0ec3f2dbc644b8466e19a5032f75a49658f13b4 Mon Sep 17 00:00:00 2001 From: Alberto Griggio Date: Thu, 7 Jun 2018 20:48:53 +0200 Subject: [PATCH 22/42] move to camconst.json the info about whether global green equilibration is needed for the camera --- rtengine/camconst.cc | 33 ++++++++++++++++++++++++++++++++ rtengine/camconst.h | 5 +++++ rtengine/camconst.json | 39 ++++++++++++++++++++++++++++++++++++++ rtengine/rawimagesource.cc | 13 +++++++++++-- 4 files changed, 88 insertions(+), 2 deletions(-) diff --git a/rtengine/camconst.cc b/rtengine/camconst.cc index 3d4342ed9..f83de99bd 100644 --- a/rtengine/camconst.cc +++ b/rtengine/camconst.cc @@ -25,6 +25,7 @@ CameraConst::CameraConst() : pdafOffset(0) memset(raw_crop, 0, sizeof(raw_crop)); memset(raw_mask, 0, sizeof(raw_mask)); white_max = 0; + globalGreenEquilibration = -1; } @@ -339,6 +340,17 @@ CameraConst::parseEntry(void *cJSON_, const char *make_model) cc->pdafOffset = ji->valueint; } + ji = cJSON_GetObjectItem(js, "global_green_equilibration"); + + if (ji) { + if (ji->type != cJSON_Number) { + fprintf(stderr, "\"global_green_equilibration\" must be a number\n"); + goto parse_error; + } + + cc->globalGreenEquilibration = ji->valueint; + } + return cc; parse_error: @@ -606,6 +618,24 @@ CameraConst::get_WhiteLevel(const int idx, const int iso_speed, const float fnum return lvl.levels[idx]; } +bool +CameraConst::has_globalGreenEquilibration() +{ + return globalGreenEquilibration >= 0; +} + +bool +CameraConst::get_globalGreenEquilibration() +{ + return globalGreenEquilibration > 0; +} + +void +CameraConst::update_globalGreenEquilibration(bool other) +{ + globalGreenEquilibration = (other ? 1 : 0); +} + bool CameraConstantsStore::parse_camera_constants_file(Glib::ustring filename_) { @@ -739,6 +769,9 @@ CameraConstantsStore::parse_camera_constants_file(Glib::ustring filename_) existingcc->update_Crop(cc); existingcc->update_pdafPattern(cc->get_pdafPattern()); existingcc->update_pdafOffset(cc->get_pdafOffset()); + if (cc->has_globalGreenEquilibration()) { + existingcc->update_globalGreenEquilibration(cc->get_globalGreenEquilibration()); + } if (settings->verbose) { printf("Merging camera constants for \"%s\"\n", make_model.c_str()); diff --git a/rtengine/camconst.h b/rtengine/camconst.h index 60e17201b..eb43da483 100644 --- a/rtengine/camconst.h +++ b/rtengine/camconst.h @@ -26,6 +26,8 @@ private: std::map mApertureScaling; std::vector pdafPattern; int pdafOffset; + int globalGreenEquilibration; + CameraConst(); static bool parseLevels(CameraConst *cc, int bw, void *ji); static bool parseApertureScaling(CameraConst *cc, void *ji); @@ -45,10 +47,13 @@ public: void get_rawMask(int idx, int& top, int& left, int& bottom, int& right); int get_BlackLevel(int idx, int iso_speed); int get_WhiteLevel(int idx, int iso_speed, float fnumber); + bool has_globalGreenEquilibration(); + bool get_globalGreenEquilibration(); void update_Levels(const CameraConst *other); void update_Crop(CameraConst *other); void update_pdafPattern(const std::vector &other); void update_pdafOffset(int other); + void update_globalGreenEquilibration(bool other); }; class CameraConstantsStore diff --git a/rtengine/camconst.json b/rtengine/camconst.json index 597c5e4d4..7763edd75 100644 --- a/rtengine/camconst.json +++ b/rtengine/camconst.json @@ -1563,6 +1563,7 @@ Camera constants: { // Quality B, 16Mp and 64Mp raw frames "make_model": "OLYMPUS E-M5MarkII", + "global_green_equilibration" : 1, "dcraw_matrix": [ 9422,-3258,-711,-2655,10898,2015,-512,1354,5512 ], // DNG_v8.8 D65 "raw_crop": [ 0, 0, -6, -6 ], // largest valid, full 64Mp 9280x6938, official crop 0 0 9216 6912 "ranges": { @@ -1604,12 +1605,14 @@ Camera constants: { // Quality B, missing per ISO samples "make_model": "OLYMPUS E-M1", + "global_green_equilibration" : 1, "dcraw_matrix": [ 7687,-1984,-606,-4327,11928,2721,-1381,2339,6452 ], // dng d65 "ranges": { "white": 4080 } // nominal 4095-4094, spread with some settings as long exposure }, { // Quality B, crop correction "make_model": [ "OLYMPUS E-M10", "OLYMPUS E-M10MarkII", "OLYMPUS E-M10 Mark III" ], + "global_green_equilibration" : 1, "dcraw_matrix": [ 8380,-2630,-639,-2887,10725,2496,-627,1427,5438 ], "raw_crop": [ 0, 0, 4624, 3472 ], // largest valid - full frame is 4640x3472 //"raw_crop": [ 4, 4, 4616, 3464 ], // olympus jpeg crop 8, 8, 4608, 3456 @@ -1618,12 +1621,14 @@ Camera constants: { // Quality A, white level correction "make_model": "OLYMPUS E-PM2", + "global_green_equilibration" : 1, "dcraw_matrix": [ 8380,-2630,-639,-2887,10725,2496,-627,1427,5438 ], "ranges": { "white": 4040 } // nominal 4056 }, { // Quality B, with long exposure noise reduction White Level gets WL-BL = around 256_12-bit levels less "make_model": [ "OLYMPUS E-PL7", "OLYMPUS E-PL8" ], + "global_green_equilibration" : 1, "dcraw_matrix": [ 9197,-3190,-659,-2606,10830,2039,-458,1250,5458 ], // DNG_v9.8 D65 "ranges": { "white": 4080 } // nominal 4093 }, @@ -1642,6 +1647,7 @@ Camera constants: { // Quality C, proper ISO 100-125-160 samples missing, pixelshift files have no black offset etc. #4574 "make_model": [ "Panasonic DC-G9" ], + "global_green_equilibration" : 1, "dcraw_matrix": [ 7685, -2375, -634, -3687, 11700, 2249, -748, 1546, 5111 ], // Adobe DNG Converter 10.3 ColorMatrix2 "ranges": { "black": 15, // 15 is BL offset. dcraw/RT reads the base black from Exif and calculates total BL = BLbase+BLoffset @@ -1655,6 +1661,7 @@ Camera constants: { // Quality B, CameraPhone, some samples are missing but has the same sensor as FZ1000 .. "make_model": [ "Panasonic DMC-CM1", "Panasonic DMC-CM10" ], + "global_green_equilibration" : 1, "dcraw_matrix": [ 8770,-3194,-820,-2871,11281,1803,-513,1552,4434 ], // dcp_v8.7 d65 "ranges": { "black": 15, // 15 is BL offset. dcraw/RT read the base BL from Exif and calculates total BL = BLbase+BLoffset @@ -1668,6 +1675,7 @@ Camera constants: { // Quality B "make_model": [ "Panasonic DC-FZ80", "Panasonic DC-FZ81", "Panasonic DC-FZ82", "Panasonic DC-FZ83" ], + "global_green_equilibration" : 1, "dcraw_matrix": [ 8550,-2908,-842,-3195,11529,1881,-338,1603,4631 ], // DNGv9.10.1 D65 "raw_crop": [ 0, 6, -8, -2 ], // fullraw4/3 5040x3688 official 8,8,4904,3680 = 4896X3672. Dcraw 0,0,4912,3688 RT's frame gets smaller than dcraw but works better with auto distortion "ranges": { "black": 15, "white": 4050 } // 15 is BL offset. dcraw/RT read the base offset from Exif and calculates total BL = BLbase+BLoffset @@ -1675,18 +1683,21 @@ Camera constants: { // Quality A, replicated from rawimage.cc "make_model": "Panasonic DMC-FZ150", + "global_green_equilibration" : 1, "dcraw_matrix": [ 10435,-3208,-72,-2293,10506,2067,-486,1725,4682 ], // RT, copy from custom dcp d55 "ranges": { "black": 15, "white": 4050 } // 15 is BL offset. dcraw/RT read the base offset from Exif and calculates total BL = BLbase+BLoffset }, { // Quality B, "make_model": [ "Panasonic DMC-FZ300", "Panasonic DMC-FZ330" ], + "global_green_equilibration" : 1, "dcraw_matrix": [ 8378,-2798,-769,-3068,11410,1877,-538,1792,4623 ], // DNG-V9.1.1 "ranges": { "black": 15, "white": 4050 } // 15 is BL offset. dcraw/RT read the base offset from Exif and calculates total BL = BLbase+BLoffset }, { // Quality A, samples by helices at RT forums "make_model": [ "Panasonic DMC-FZ1000", "Leica V-LUX (Typ 114)" ], + "global_green_equilibration" : 1, "dcraw_matrix": [ 7830,-2696,-763,-3325,11667,1866,-641,1712,4824 ], // dcp_v8.6 d65 "ranges": { "black": 15, // 15 is BL offset. dcraw/RT read the base BL from Exif and calculates total BL = BLbase+BLoffset @@ -1700,6 +1711,7 @@ Camera constants: { // Quality B, "make_model": [ "Panasonic DMC-FZ2500", "Panasonic DMC-FZ2000", "Panasonic DMC-FZH1" ], + "global_green_equilibration" : 1, "dcraw_matrix": [ 7386,-2443,-743,-3437,11864,1757,-608,1660,4766 ], // dcp_v9.8 d65 "ranges": { "black": 15, // 15 is BL offset. dcraw/RT read the base BL from Exif and calculates total BL = BLbase+BLoffset @@ -1713,6 +1725,7 @@ Camera constants: { // Quality A, samples by helices at RT forums and Chris Power at github "make_model": [ "Panasonic DMC-ZS100", "Panasonic DMC-ZS110", "Panasonic DMC-TZ100", "Panasonic DMC-TZ101", "Panasonic DMC-TZ110", "Panasonic DMC-TX1" ], + "global_green_equilibration" : 1, "dcraw_matrix": [ 7790,-2736,-755,-3452,11870,1769,-628,1647,4898 ], // dcp_v8.6 d65 "raw_crop": [ 4, 4, -4, -4 ], // full raw frame 5488x3664 Exif crop 5472X3648 with 8pixel borders. Set the borders at 4 pixels which added with RT's 4 pixels border gives exactly the official frame. "ranges": { @@ -1727,12 +1740,14 @@ Camera constants: { // Quality A "make_model": [ "Panasonic DMC-LF1", "Leica C (Typ 112)" ], + "global_green_equilibration" : 1, "dcraw_matrix": [ 9379,-3267,-816,-3227,11560,1881,-926,1928,5340 ], "ranges": { "black": 15, "white": 4050 } // 15 is BL offset. dcraw/RT read the base offset from Exif and calculates total BL = BLbase+BLoffset }, { // Quality A "make_model": [ "Panasonic DMC-TZ60", "Panasonic DMC-TZ61", "Panasonic DMC-ZS40", "Panasonic DMC-ZS41" ], + "global_green_equilibration" : 1, "dcraw_matrix": [ 8607,-2822,-808,-3755,11930,2049,-820,2060,5224 ], // matrix from Adobe dcp v8.4 "raw_crop": [ 8, 8, -8, -8 ], // crop according to Exif 4896 X 3672 plus 4 pixels borders. RT's frame gets smaller than dcraw but works better with auto distortion "ranges": { "black": 14, "white": 4050 } // 15 is BL offset. dcraw/RT read the base offset from Exif and calculates total BL = BLbase+BLoffset @@ -1740,6 +1755,7 @@ Camera constants: { // Quality B "make_model": [ "Panasonic DMC-TZ70", "Panasonic DMC-TZ71", "Panasonic DMC-ZS50", "Panasonic DMC-ZS51" ], + "global_green_equilibration" : 1, "dcraw_matrix": [ 8802,-3135,-789,-3151,11468,1904,-550,1745,4810 ], // DNG_V8.8 D65 "raw_crop": [ 0, 0, -4, -4 ], // full raw 4/3 4144x3016 8,8,3008,4008 = 4000X3000. RT's frame gets smaller than dcraw but works better with auto distortion "ranges": { "black": 14, "white": 4050 } // 12+1+1 is BL offset @@ -1747,6 +1763,7 @@ Camera constants: { // Quality A, samples by Hombre "make_model": [ "Panasonic DC-ZS70", "Panasonic DC-TZ90", "Panasonic DC-TZ91", "Panasonic DC-TZ92", "Panasonic DC-TZ93" ], + "global_green_equilibration" : 1, "dcraw_matrix": [ 9052,-3117,-883,-3045,11346,1927,-205,1520,4730 ], // DNG_V9.10.1 D65 "raw_crop": [ 0, 6, -8, -2 ], // fullraw4/3 5264x3904 official 8,8,3896,5192 = 5184X3888. Dcraw 0,0,5200,3904 RT's frame gets smaller than dcraw but works better with auto distortion "ranges": { "black": 16, "white": 4050 } // 12+3+1 is BL offset @@ -1756,6 +1773,7 @@ Camera constants: { // Quality A, Replicated from rawimage.cc "make_model": [ "Panasonic DMC-G10", "Panasonic DMC-G2" ], + "global_green_equilibration" : 1, "dcraw_matrix": [ 8310,-1811,-960,-4941,12990,2151,-1378,2468,6860 ], // Colin Walker "ranges": { "black": 15, // 15 is black offset, dcraw/RT read the base black from Exif and calculates total BL = BLbase+BLoffset @@ -1768,6 +1786,7 @@ Camera constants: { // Quality A, Replicated from rawimage.cc "make_model": "Panasonic DMC-G1", + "global_green_equilibration" : 1, "dcraw_matrix": [ 7477,-1615,-651,-5016,12769,2506,-1380,2475,7240 ], // Colin Walker "ranges": { "black": 15, // 15 is BL offset. dcraw/RT read the base black from Exif and calculates total BL = BLbase+BLoffset @@ -1780,6 +1799,7 @@ Camera constants: { // Quality A, Replicated from rawimage.cc "make_model": "Panasonic DMC-G3", + "global_green_equilibration" : 1, "dcraw_matrix": [ 6051,-1406,-671,-4015,11505,2868,-1654,2667,6219 ], // Colin Walker "ranges": { "black": 15, // 15 is BL offset. dcraw/RT read the base black from Exif and calculates total BL = BLbase+BLoffset @@ -1788,6 +1808,7 @@ Camera constants: { // Quality A, Replicated from rawimage.cc "make_model": "Panasonic DMC-G5", + "global_green_equilibration" : 1, "dcraw_matrix": [ 7122,-2092,-419,-4643,11769,3283,-1363,2413,5944 ], // RT "ranges": { "black": 15, // 15 is BL offset. dcraw/RT read the base black from Exif and calculates total BL = BLbase+BLoffset @@ -1796,6 +1817,7 @@ Camera constants: { // Quality A, Replicated from rawimage.cc "make_model": "Panasonic DMC-GF1", + "global_green_equilibration" : 1, "dcraw_matrix": [ 7863,-2080,-668,-4623,12331,2578,-1020,2066,7266 ], // Colin Walker "ranges": { "black": 15, // 15 is BL offset. dcraw/RT read the base black from Exif and calculates total BL = BLbase+BLoffset @@ -1808,6 +1830,7 @@ Camera constants: { // Quality A, Replicated from rawimage.cc "make_model": "Panasonic DMC-GF2", + "global_green_equilibration" : 1, "dcraw_matrix": [ 7694,-1791,-745,-4917,12818,2332,-1221,2322,7197 ], // Colin Walker "ranges": { "black": 15, // 15 is BL offset. dcraw/RT read the base black from Exif and calculates total BL = BLbase+BLoffset @@ -1816,6 +1839,7 @@ Camera constants: { // Quality A, Replicated from rawimage.cc "make_model": "Panasonic DMC-GF3", + "global_green_equilibration" : 1, "dcraw_matrix": [ 8074,-1846,-861,-5026,12999,2239,-1320,2375,7422 ], // Colin Walker "ranges": { "black": 15, // 15 is BL offset. dcraw/RT read the base black from Exif and calculates total BL = BLbase+BLoffset @@ -1824,6 +1848,7 @@ Camera constants: { // Quality A, Replicated from rawimage.cc "make_model": "Panasonic DMC-GH1", + "global_green_equilibration" : 1, "dcraw_matrix": [ 6360,-1557,-375,-4201,11504,3086,-1378,2518,5843 ], // Colin Walker "ranges": { "black": 15, // 15 is BL offset. dcraw/RT read the base black from Exif and calculates total BL = BLbase+BLoffset @@ -1836,6 +1861,7 @@ Camera constants: { // Quality A, Replicated from rawimage.cc "make_model": "Panasonic DMC-GH2", + "global_green_equilibration" : 1, //"dcraw_matrix": [ 6855,-1765,-456,-4223,11600,2996,-1450,2602,5761 ], // Colin Walker - disabled due to problems with underwater "dcraw_matrix": [ 7780,-2410,-806,-3913,11724,2484,-1018,2390,5298 ], // dcraw d65 "ranges": { @@ -1849,6 +1875,7 @@ Camera constants: { // Quality B, variable WL "make_model": "Panasonic DMC-GH3", + "global_green_equilibration" : 1, "dcraw_matrix": [ 6559,-1752,-491,-3672,11407,2586,-962,1875,5130 ], // dcp d65 "ranges": { "black": 16, // 16 is BL offset. dcraw/RT read the base black from Exif and calculates total BL = BLbase+BLoffset @@ -1861,6 +1888,7 @@ Camera constants: { // Quality B, some ISO WLevels are safely guessed "make_model": "Panasonic DMC-GH4", + "global_green_equilibration" : 1, "dcraw_matrix": [ 7122,-2108,-512,-3155,11201,2231,-541,1423,5045 ], // dng_v8.5 d65 "ranges": { "black": 16, // 16 is BL offset. dcraw/RT read the base black from Exif and calculates total BL = BLbase+BLoffset @@ -1874,6 +1902,7 @@ Camera constants: { // Quality C "make_model": "Panasonic DC-GH5", + "global_green_equilibration" : 1, "dcraw_matrix": [ 7641,-2336,-605,-3218,11299,2187,-485,1338,5121 ], // DNG_v9.9 D65 "ranges": { "black": 15, // 16 is BL offset. dcraw/RT read the base BL from Exif and calculates total BL = BLbase+BLoffset @@ -1887,6 +1916,7 @@ Camera constants: { // Quality A "make_model": "Panasonic DMC-GM1", + "global_green_equilibration" : 1, "dcraw_matrix": [ 6770,-1895,-744,-5232,13145,2303,-1664,2691,5703 ], "ranges": { "black": 15, // 15 is BL offset. dcraw/RT read the base black from Exif and calculates total BL = BLbase+BLoffset @@ -1900,6 +1930,7 @@ Camera constants: { // Quality B, uncertainty about ISO100 WL "make_model": "Panasonic DMC-GM5", + "global_green_equilibration" : 1, "dcraw_matrix": [ 8238,-3244,-679,-3921,11814,2384,-836,2022,5852 ], // dng_v8.7 d65 "ranges": { "black": 15, // 15 is BL offset. dcraw/RT read the base black from Exif and calculates total BL = BLbase+BLoffset @@ -1912,6 +1943,7 @@ Camera constants: { // Quality A "make_model": [ "Panasonic DMC-GX7", "Panasonic DMC-GF7", "Panasonic DMC-GF8" ], + "global_green_equilibration" : 1, "dcraw_matrix": [ 7610,-2780,-576,-4614,12195,2733,-1375,2393,6490 ], "ranges": { "black": 15, // 15 is BL offset. dcraw/RT read the base black from Exif and calculates total BL = BLbase+BLoffset @@ -1925,6 +1957,7 @@ Camera constants: { // Quality A "make_model": [ "Panasonic DMC-G7", "Panasonic DMC-G70" ], + "global_green_equilibration" : 1, "dcraw_matrix": [ 7610,-2780,-576,-4614,12195,2733,-1375,2393,6490 ], // DNG_v9.1 D65 "ranges": { "black": 16, // 16 is BL offset. dcraw/RT read the base black from Exif and calculates total BL = BLbase+BLoffset @@ -1938,6 +1971,7 @@ Camera constants: { // Quality B "make_model": [ "Panasonic DMC-GX80", "Panasonic DMC-GX85", "Panasonic DMC-GX7MK2" ], + "global_green_equilibration" : 1, "dcraw_matrix": [ 7771,-3020,-629,-4029,11950,2345,-821,1977,6119 ], // DNG_v9.6 D65 "ranges": { "black": 16, // 16 is BL offset. dcraw/RT read the base black from Exif and calculates total BL = BLbase+BLoffset @@ -1951,6 +1985,7 @@ Camera constants: { // Quality X, no white-frames nor black-frames yet, see #4550 "make_model": [ "Panasonic DC-GX9" ], + "global_green_equilibration" : 1, "dcraw_matrix": [ 7564,-2263,-606,-3148,11239,2177,-540,1435,4853 ], // ColorMatrix2 from Adobe DNG Converter 10.3 "ranges": { "black": 16, @@ -1960,6 +1995,7 @@ Camera constants: { // Quality B, Same as Panasonic G7 "make_model": [ "Panasonic DMC-G8", "Panasonic DMC-G80", "Panasonic DMC-G81", "Panasonic DMC-G85" ], + "global_green_equilibration" : 1, "dcraw_matrix": [ 7610,-2780,-576,-4614,12195,2733,-1375,2393,6490 ], // DNG_v9.7 D65 "ranges": { "black": 16, // 16 is BL offset. dcraw/RT read the base black from Exif and calculates total BL = BLbase+BLoffset @@ -1973,6 +2009,7 @@ Camera constants: { // Quality B "make_model": "Panasonic DMC-GX8", + "global_green_equilibration" : 1, "dcraw_matrix": [ 7564,-2263,-606,-3148,11239,2177,-540,1435,4853 ], // DNG_v9.1.1 D65 "ranges": { "black": 15, // 16 is BL offset. dcraw/RT read the base BL from Exif and calculates total BL = BLbase+BLoffset @@ -1986,6 +2023,7 @@ Camera constants: { // Quality B, samples by Ingo, missing some long exposure at high ISO samples with LENR ON "make_model": [ "Panasonic DMC-LX100", "Leica D-LUX (Typ 109)" ], + "global_green_equilibration" : 1, "dcraw_matrix": [ 8844,-3538,-768,-3709,11762,2200,-698,1792,5220 ], // DNG_V8.7 d65 //"dcraw_matrix": [ 6538,-1614,-549,-5475,13096,2646,-1780,2799,5612 ], // calculated from DxO D50 "ranges": { @@ -2006,6 +2044,7 @@ Camera constants: { // Quality B, Intermediate ISOs missing "make_model": [ "Panasonic DMC-LX9", "Panasonic DMC-LX10", "Panasonic DMC-LX15" ], + "global_green_equilibration" : 1, "dcraw_matrix": [ 7790,-2736,-755,-3452,11870,1769,-628,1647,4898 ], // DNg_v9.8 d65 "raw_crop": [ 4, 4, -4, -4 ], // full raw frame 5488x3664 Exif crop 5472X3648 with 8pixel borders. Set the borders at 4 pixels which added with RT's 4 pixels border gives exactly the official frame. "ranges": { diff --git a/rtengine/rawimagesource.cc b/rtengine/rawimagesource.cc index 6f119a2ad..0c35154bf 100644 --- a/rtengine/rawimagesource.cc +++ b/rtengine/rawimagesource.cc @@ -35,6 +35,7 @@ #include "improcfun.h" #include "rtlensfun.h" #include "pdaflinesfilter.h" +#include "camconst.h" #ifdef _OPENMP #include #endif @@ -1945,8 +1946,16 @@ void RawImageSource::preprocess (const RAWParams &raw, const LensProfParams &le } } - // check if it is an olympus E camera or green equilibration is enabled. If yes, compute G channel pre-compensation factors - if ( ri->getSensorType() == ST_BAYER && (raw.bayersensor.greenthresh || (((idata->getMake().size() >= 7 && idata->getMake().substr(0, 7) == "OLYMPUS" && idata->getModel()[0] == 'E') || (idata->getMake().size() >= 9 && idata->getMake().substr(0, 9) == "Panasonic")) && raw.bayersensor.method != RAWParams::BayerSensor::getMethodString( RAWParams::BayerSensor::Method::VNG4))) ) { + // check if green equilibration is needed. If yes, compute G channel pre-compensation factors + const auto globalGreenEq = + [&]() -> bool + { + CameraConstantsStore *ccs = CameraConstantsStore::getInstance(); + CameraConst *cc = ccs->get(ri->get_maker().c_str(), ri->get_model().c_str()); + return cc && cc->get_globalGreenEquilibration(); + }; + + if ( ri->getSensorType() == ST_BAYER && (raw.bayersensor.greenthresh || (globalGreenEq() && raw.bayersensor.method != RAWParams::BayerSensor::getMethodString( RAWParams::BayerSensor::Method::VNG4))) ) { // global correction if(numFrames == 4) { for(int i = 0; i < 4; ++i) { From 0e22f0b610bef09abf8815535c6052d9a4095af5 Mon Sep 17 00:00:00 2001 From: Alberto Griggio Date: Thu, 7 Jun 2018 20:50:32 +0200 Subject: [PATCH 23/42] camconst.json: rename pdafPattern -> pdaf_pattern and pdafOffset -> pdaf_offset this is for consistency with the other entries --- rtengine/camconst.cc | 10 +++++----- rtengine/camconst.json | 30 +++++++++++++++--------------- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/rtengine/camconst.cc b/rtengine/camconst.cc index f83de99bd..3e6139fc6 100644 --- a/rtengine/camconst.cc +++ b/rtengine/camconst.cc @@ -311,17 +311,17 @@ CameraConst::parseEntry(void *cJSON_, const char *make_model) } } - ji = cJSON_GetObjectItem(js, "pdafPattern"); + ji = cJSON_GetObjectItem(js, "pdaf_pattern"); if (ji) { if (ji->type != cJSON_Array) { - fprintf(stderr, "\"pdafPattern\" must be an array\n"); + fprintf(stderr, "\"pdaf_pattern\" must be an array\n"); goto parse_error; } for (ji = ji->child; ji != nullptr; ji = ji->next) { if (ji->type != cJSON_Number) { - fprintf(stderr, "\"pdafPattern\" array must contain numbers\n"); + fprintf(stderr, "\"pdaf_pattern\" array must contain numbers\n"); goto parse_error; } @@ -329,11 +329,11 @@ CameraConst::parseEntry(void *cJSON_, const char *make_model) } } - ji = cJSON_GetObjectItem(js, "pdafOffset"); + ji = cJSON_GetObjectItem(js, "pdaf_offset"); if (ji) { if (ji->type != cJSON_Number) { - fprintf(stderr, "\"pdafOffset\" must contain a number\n"); + fprintf(stderr, "\"pdaf_offset\" must contain a number\n"); goto parse_error; } diff --git a/rtengine/camconst.json b/rtengine/camconst.json index 7763edd75..4772868a1 100644 --- a/rtengine/camconst.json +++ b/rtengine/camconst.json @@ -83,10 +83,10 @@ Examples: // instead, to take care of possible light leaks from the light sensing area to the optically black (masked) // area or sensor imperfections at the outer borders. - // list of indices of the rows with on-sensor PDAF pixels, for cameras that have such features. The indices here form a pattern that is repeated for the whole height of the sensor. The values are relative to the "pdafOffset" value (see below) - "pdafPattern" : [ 0,12,36,54,72,90,114,126,144,162,180,204,216,240,252,270,294,306,324,342,366,384,396,414,432,450,474,492,504,522,540,564,576,594,606,630 ], + // list of indices of the rows with on-sensor PDAF pixels, for cameras that have such features. The indices here form a pattern that is repeated for the whole height of the sensor. The values are relative to the "pdaf_offset" value (see below) + "pdaf_pattern" : [ 0,12,36,54,72,90,114,126,144,162,180,204,216,240,252,270,294,306,324,342,366,384,396,414,432,450,474,492,504,522,540,564,576,594,606,630 ], // index of the first row of the PDAF pattern in the sensor (0 is the topmost row). Allowed to be negative for convenience (this means that the first repetition of the pattern doesn't start from the first row) - "pdafOffset" : 3 + "pdaf_offset" : 3 }, { @@ -2308,8 +2308,8 @@ Camera constants: "ranges": { "black": 512, "white": 16300 }, // detected by hand, using the picture from https://www.dpreview.com/forums/thread/3923513 // P 11 P 23 P 17 P 17 P 17 P 23 P 11 P 17 P 17 P 17 P 23 P 11 P 23 P 11 P 17 P 23 P 11 P 17 P 17 P 23 P 17 P 11 P 17 P 17 P 17 P 23 P 17 P 11 P 17 P 17 P 23 P 11 P 17 P 11 P 23 - "pdafPattern" : [ 0,12,36,54,72,90,114,126,144,162,180,204,216,240,252,270,294,306,324,342,366,384,396,414,432,450,474,492,504,522,540,564,576,594,606,630 ], - "pdafOffset" : 3 + "pdaf_pattern" : [ 0,12,36,54,72,90,114,126,144,162,180,204,216,240,252,270,294,306,324,342,366,384,396,414,432,450,474,492,504,522,540,564,576,594,606,630 ], + "pdaf_offset" : 3 }, { // Quality A @@ -2318,8 +2318,8 @@ Camera constants: "raw_crop": [ 0, 0, 6024, 4024 ], "ranges": { "black": 512, "white": 16300 }, // contributed by Horshak from https://www.dpreview.com/forums/post/60873077 - "pdafPattern" : [ 0,12,36,54,72,90,114,126,144,162,180,204,216,240,252,270,294,306,324,342,366,384,396,414,432,450,474,492,504,522,540,564,576,594,606,630 ], - "pdafOffset" : 3 + "pdaf_pattern" : [ 0,12,36,54,72,90,114,126,144,162,180,204,216,240,252,270,294,306,324,342,366,384,396,414,432,450,474,492,504,522,540,564,576,594,606,630 ], + "pdaf_offset" : 3 }, { // Quality C, only pdaf data @@ -2330,8 +2330,8 @@ Camera constants: // // rotated to match the start of the frame // P 11 P 11 P 11 P 17 P 11 P 5 P 11 P 11 P 17 P 5 P 11 P 17 P 5 P 17 P 5 P 11 P 11 P 11 P 17 P 5 P 11 P 11 P 11 P 5 P 17 P 5 P 17 P 11 P 5 P 17 P 11 P 11 P 17 P 11 P 5 - "pdafPattern" : [ 0,12,24,36,54,66,72,84,96,114,120,132,150,156,174,180,192,204,216,234,240,252,264,276,282,300,306,324,336,342,360,372,384,402,414,420], - "pdafOffset" : 9 + "pdaf_pattern" : [ 0,12,24,36,54,66,72,84,96,114,120,132,150,156,174,180,192,204,216,234,240,252,264,276,282,300,306,324,336,342,360,372,384,402,414,420], + "pdaf_offset" : 9 }, { // Quality A, correction for frame width @@ -2353,8 +2353,8 @@ Camera constants: "raw_crop": [ 0, 0, -36, 0 ], // full raw frame 8000x5320 - 36 rightmost columns are garbage "ranges": { "black": 512, "white": 16300 }, // PDAF info provided by Horshack with the rawshack tool (http://testcams.com/rawshack/) - "pdafPattern" : [ 0,24,36,60,84,120,132,156,192,204,240,252,276,300,324,360,372,396,420 ], - "pdafOffset" : 31 + "pdaf_pattern" : [ 0,24,36,60,84,120,132,156,192,204,240,252,276,300,324,360,372,396,420 ], + "pdaf_offset" : 31 }, { // Quality C, color matrix copied from ILCE-9, LongExposures 2-3sec only @@ -2384,8 +2384,8 @@ Camera constants: "dcraw_matrix": [ 6640,-1847,-503,-5238,13010,2474,-993,1673,6527 ], // DNG_v10.1 D65 "raw_crop": [ 0, 0, -36, 0 ], // full raw frame 8000x5320 - 36 rightmost columns are garbage "ranges": { "black": 512, "white": 16300 }, - "pdafPattern" : [0, 24, 36, 60, 84, 120, 132, 156, 192, 204, 240, 252, 276, 300, 324, 360, 372, 396, 420, 444, 480, 492, 504, 540, 564, 576, 612, 636, 660, 696, 720, 732, 756, 780, 804, 840], - "pdafOffset" : 31 + "pdaf_pattern" : [0, 24, 36, 60, 84, 120, 132, 156, 192, 204, 240, 252, 276, 300, 324, 360, 372, 396, 420, 444, 480, 492, 504, 540, 564, 576, 612, 636, 660, 696, 720, 732, 756, 780, 804, 840], + "pdaf_offset" : 31 }, { // Quality B, color matrix copied from a7rm2 @@ -2396,8 +2396,8 @@ Camera constants: // the A9 is the same as the A7III, rotated of 1 position // source: https://www.dpreview.com/forums/post/60857788 // P 11 P 11 P 11 P 17 P 11 P 5 P 11 P 11 P 17 P 5 P 11 P 17 P 5 P 17 P 5 P 11 P 11 P 11 P 17 P 5 P 11 P 11 P 11 P 5 P 17 P 5 P 17 P 11 P 5 P 17 P 11 P 11 P 17 P 11 P 5 - "pdafPattern" : [ 0,12,24,36,54,66,72,84,96,114,120,132,150,156,174,180,192,204,216,234,240,252,264,276,282,300,306,324,336,342,360,372,384,402,414,420 ], - "pdafOffset" : -7 + "pdaf_pattern" : [ 0,12,24,36,54,66,72,84,96,114,120,132,150,156,174,180,192,204,216,234,240,252,264,276,282,300,306,324,336,342,360,372,384,402,414,420 ], + "pdaf_offset" : -7 }, { // Quality B, correction for frame width From fc4d0fb076e8999d4c366c9cb1e16721fe862ec7 Mon Sep 17 00:00:00 2001 From: heckflosse Date: Thu, 7 Jun 2018 21:38:10 +0200 Subject: [PATCH 24/42] Removed Benchmark code --- rtengine/amaze_vng4_demosaic_RT.cc | 2 +- rtengine/vng4_demosaic_RT.cc | 12 ++++-------- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/rtengine/amaze_vng4_demosaic_RT.cc b/rtengine/amaze_vng4_demosaic_RT.cc index 841abf9d3..08e142a4e 100644 --- a/rtengine/amaze_vng4_demosaic_RT.cc +++ b/rtengine/amaze_vng4_demosaic_RT.cc @@ -26,7 +26,7 @@ #include "rtengine.h" #include "rawimagesource.h" #include "rt_math.h" -#define BENCHMARK +//#define BENCHMARK #include "StopWatch.h" #include "rt_algo.h" diff --git a/rtengine/vng4_demosaic_RT.cc b/rtengine/vng4_demosaic_RT.cc index b996559b4..d6520607e 100644 --- a/rtengine/vng4_demosaic_RT.cc +++ b/rtengine/vng4_demosaic_RT.cc @@ -23,9 +23,8 @@ #include "rtengine.h" #include "rawimagesource.h" #include "rawimagesource_i.h" -//#include "rt_math.h" #include "../rtgui/multilangmgr.h" -#define BENCHMARK +//#define BENCHMARK #include "StopWatch.h" namespace rtengine @@ -75,7 +74,7 @@ void RawImageSource::vng4_demosaic (const array2D &rawData, array2DsetProgress (progress); } -StopWatch Stop3("loop3"); #ifdef _OPENMP #pragma omp parallel #endif @@ -322,7 +318,7 @@ StopWatch Stop3("loop3"); if(plistenerActive) { plistener->setProgress (0.98); } -Stop3.stop(); + // Interpolate R and B #ifdef _OPENMP #pragma omp parallel for From ee4f990eadf6a8165602f0c07232578410bd37b4 Mon Sep 17 00:00:00 2001 From: heckflosse Date: Thu, 7 Jun 2018 21:38:46 +0200 Subject: [PATCH 25/42] Reduced maximum value for dual demosaic contrast threshold to 100 --- rtgui/bayerprocess.cc | 3 +-- rtgui/xtransprocess.cc | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/rtgui/bayerprocess.cc b/rtgui/bayerprocess.cc index 26475bc90..c6f04c053 100644 --- a/rtgui/bayerprocess.cc +++ b/rtgui/bayerprocess.cc @@ -101,9 +101,8 @@ BayerProcess::BayerProcess () : FoldableToolPanel(this, "bayerprocess", M("TP_RA dualDemosaicOptions = Gtk::manage (new Gtk::VBox ()); - dualDemosaicContrast = Gtk::manage(new Adjuster (M("TP_RAW_DUALDEMOSAICCONTRAST"), 0, 200, 1, 20)); + dualDemosaicContrast = Gtk::manage(new Adjuster (M("TP_RAW_DUALDEMOSAICCONTRAST"), 0, 100, 1, 20)); dualDemosaicContrast->setAdjusterListener (this); -// dualDemosaicContrast->set_tooltip_markup (M("TP_RAW_LMMSE_TOOLTIP")); if (dualDemosaicContrast->delay < options.adjusterMaxDelay) { dualDemosaicContrast->delay = options.adjusterMaxDelay; diff --git a/rtgui/xtransprocess.cc b/rtgui/xtransprocess.cc index 334f0d0d9..1b2b4a40d 100644 --- a/rtgui/xtransprocess.cc +++ b/rtgui/xtransprocess.cc @@ -69,9 +69,8 @@ XTransProcess::XTransProcess () : FoldableToolPanel(this, "xtransprocess", M("TP dualDemosaicOptions = Gtk::manage (new Gtk::VBox ()); - dualDemosaicContrast = Gtk::manage(new Adjuster (M("TP_RAW_DUALDEMOSAICCONTRAST"), 0, 200, 1, 20)); + dualDemosaicContrast = Gtk::manage(new Adjuster (M("TP_RAW_DUALDEMOSAICCONTRAST"), 0, 100, 1, 20)); dualDemosaicContrast->setAdjusterListener (this); -// dualDemosaicContrast->set_tooltip_markup (M("TP_RAW_LMMSE_TOOLTIP")); if (dualDemosaicContrast->delay < options.adjusterMaxDelay) { dualDemosaicContrast->delay = options.adjusterMaxDelay; From d624577ee55de0550f488073b3c0b32ff20c8dae Mon Sep 17 00:00:00 2001 From: heckflosse Date: Thu, 7 Jun 2018 22:08:07 +0200 Subject: [PATCH 26/42] Removed accidently committed condition --- rtengine/rawimagesource.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rtengine/rawimagesource.cc b/rtengine/rawimagesource.cc index 5d654317c..25c732947 100644 --- a/rtengine/rawimagesource.cc +++ b/rtengine/rawimagesource.cc @@ -1952,7 +1952,7 @@ void RawImageSource::preprocess (const RAWParams &raw, const LensProfParams &le for(int i = 0; i < 4; ++i) { green_equilibrate_global(*rawDataFrames[i]); } - } else if(idata->getModel() != "E-M1MarkII") { + } else { green_equilibrate_global(rawData); } } From 6cba9ab7c449a87923e122a3d1638fa1776d06a0 Mon Sep 17 00:00:00 2001 From: heckflosse Date: Thu, 7 Jun 2018 22:11:37 +0200 Subject: [PATCH 27/42] Fixed another accidently committed change --- rtengine/green_equil_RT.cc | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/rtengine/green_equil_RT.cc b/rtengine/green_equil_RT.cc index 77365dc21..361bde882 100644 --- a/rtengine/green_equil_RT.cc +++ b/rtengine/green_equil_RT.cc @@ -46,14 +46,12 @@ void RawImageSource::green_equilibrate_global(array2D &rawData) for (int i = border; i < H - border; i++) { double avgg = 0.; - int ng = 0; for (int j = border + ((FC(i, border) & 1) ^ 1); j < W - border; j += 2) { -// if(rawData[i][j] > 0.f) { - avgg += rawData[i][j]; - ng++; -// } + avgg += rawData[i][j]; } + int ng = (W - 2 * border + (FC(i, border) & 1)) / 2; + if (i & 1) { avgg2 += avgg; ng2 += ng; From 4361e1206217f2d5cbff16e2b207bbf04df8eda7 Mon Sep 17 00:00:00 2001 From: Alberto Griggio Date: Fri, 8 Jun 2018 13:55:15 +0200 Subject: [PATCH 28/42] camconst: use true/false instead of 0/1 for "global_green_equilibration" --- rtengine/camconst.cc | 6 +-- rtengine/camconst.json | 78 +++++++++++++++++++------------------- rtengine/rawimagesource.cc | 3 ++ 3 files changed, 45 insertions(+), 42 deletions(-) diff --git a/rtengine/camconst.cc b/rtengine/camconst.cc index 3e6139fc6..43de5d688 100644 --- a/rtengine/camconst.cc +++ b/rtengine/camconst.cc @@ -343,12 +343,12 @@ CameraConst::parseEntry(void *cJSON_, const char *make_model) ji = cJSON_GetObjectItem(js, "global_green_equilibration"); if (ji) { - if (ji->type != cJSON_Number) { - fprintf(stderr, "\"global_green_equilibration\" must be a number\n"); + if (ji->type != cJSON_False && ji->type != cJSON_True) { + fprintf(stderr, "\"global_green_equilibration\" must be a boolean\n"); goto parse_error; } - cc->globalGreenEquilibration = ji->valueint; + cc->globalGreenEquilibration = (ji->type == cJSON_True); } return cc; diff --git a/rtengine/camconst.json b/rtengine/camconst.json index 4772868a1..bfa22567c 100644 --- a/rtengine/camconst.json +++ b/rtengine/camconst.json @@ -1563,7 +1563,7 @@ Camera constants: { // Quality B, 16Mp and 64Mp raw frames "make_model": "OLYMPUS E-M5MarkII", - "global_green_equilibration" : 1, + "global_green_equilibration" : true, "dcraw_matrix": [ 9422,-3258,-711,-2655,10898,2015,-512,1354,5512 ], // DNG_v8.8 D65 "raw_crop": [ 0, 0, -6, -6 ], // largest valid, full 64Mp 9280x6938, official crop 0 0 9216 6912 "ranges": { @@ -1605,14 +1605,14 @@ Camera constants: { // Quality B, missing per ISO samples "make_model": "OLYMPUS E-M1", - "global_green_equilibration" : 1, + "global_green_equilibration" : true, "dcraw_matrix": [ 7687,-1984,-606,-4327,11928,2721,-1381,2339,6452 ], // dng d65 "ranges": { "white": 4080 } // nominal 4095-4094, spread with some settings as long exposure }, { // Quality B, crop correction "make_model": [ "OLYMPUS E-M10", "OLYMPUS E-M10MarkII", "OLYMPUS E-M10 Mark III" ], - "global_green_equilibration" : 1, + "global_green_equilibration" : true, "dcraw_matrix": [ 8380,-2630,-639,-2887,10725,2496,-627,1427,5438 ], "raw_crop": [ 0, 0, 4624, 3472 ], // largest valid - full frame is 4640x3472 //"raw_crop": [ 4, 4, 4616, 3464 ], // olympus jpeg crop 8, 8, 4608, 3456 @@ -1621,14 +1621,14 @@ Camera constants: { // Quality A, white level correction "make_model": "OLYMPUS E-PM2", - "global_green_equilibration" : 1, + "global_green_equilibration" : true, "dcraw_matrix": [ 8380,-2630,-639,-2887,10725,2496,-627,1427,5438 ], "ranges": { "white": 4040 } // nominal 4056 }, { // Quality B, with long exposure noise reduction White Level gets WL-BL = around 256_12-bit levels less "make_model": [ "OLYMPUS E-PL7", "OLYMPUS E-PL8" ], - "global_green_equilibration" : 1, + "global_green_equilibration" : true, "dcraw_matrix": [ 9197,-3190,-659,-2606,10830,2039,-458,1250,5458 ], // DNG_v9.8 D65 "ranges": { "white": 4080 } // nominal 4093 }, @@ -1647,7 +1647,7 @@ Camera constants: { // Quality C, proper ISO 100-125-160 samples missing, pixelshift files have no black offset etc. #4574 "make_model": [ "Panasonic DC-G9" ], - "global_green_equilibration" : 1, + "global_green_equilibration" : true, "dcraw_matrix": [ 7685, -2375, -634, -3687, 11700, 2249, -748, 1546, 5111 ], // Adobe DNG Converter 10.3 ColorMatrix2 "ranges": { "black": 15, // 15 is BL offset. dcraw/RT reads the base black from Exif and calculates total BL = BLbase+BLoffset @@ -1661,7 +1661,7 @@ Camera constants: { // Quality B, CameraPhone, some samples are missing but has the same sensor as FZ1000 .. "make_model": [ "Panasonic DMC-CM1", "Panasonic DMC-CM10" ], - "global_green_equilibration" : 1, + "global_green_equilibration" : true, "dcraw_matrix": [ 8770,-3194,-820,-2871,11281,1803,-513,1552,4434 ], // dcp_v8.7 d65 "ranges": { "black": 15, // 15 is BL offset. dcraw/RT read the base BL from Exif and calculates total BL = BLbase+BLoffset @@ -1675,7 +1675,7 @@ Camera constants: { // Quality B "make_model": [ "Panasonic DC-FZ80", "Panasonic DC-FZ81", "Panasonic DC-FZ82", "Panasonic DC-FZ83" ], - "global_green_equilibration" : 1, + "global_green_equilibration" : true, "dcraw_matrix": [ 8550,-2908,-842,-3195,11529,1881,-338,1603,4631 ], // DNGv9.10.1 D65 "raw_crop": [ 0, 6, -8, -2 ], // fullraw4/3 5040x3688 official 8,8,4904,3680 = 4896X3672. Dcraw 0,0,4912,3688 RT's frame gets smaller than dcraw but works better with auto distortion "ranges": { "black": 15, "white": 4050 } // 15 is BL offset. dcraw/RT read the base offset from Exif and calculates total BL = BLbase+BLoffset @@ -1683,21 +1683,21 @@ Camera constants: { // Quality A, replicated from rawimage.cc "make_model": "Panasonic DMC-FZ150", - "global_green_equilibration" : 1, + "global_green_equilibration" : true, "dcraw_matrix": [ 10435,-3208,-72,-2293,10506,2067,-486,1725,4682 ], // RT, copy from custom dcp d55 "ranges": { "black": 15, "white": 4050 } // 15 is BL offset. dcraw/RT read the base offset from Exif and calculates total BL = BLbase+BLoffset }, { // Quality B, "make_model": [ "Panasonic DMC-FZ300", "Panasonic DMC-FZ330" ], - "global_green_equilibration" : 1, + "global_green_equilibration" : true, "dcraw_matrix": [ 8378,-2798,-769,-3068,11410,1877,-538,1792,4623 ], // DNG-V9.1.1 "ranges": { "black": 15, "white": 4050 } // 15 is BL offset. dcraw/RT read the base offset from Exif and calculates total BL = BLbase+BLoffset }, { // Quality A, samples by helices at RT forums "make_model": [ "Panasonic DMC-FZ1000", "Leica V-LUX (Typ 114)" ], - "global_green_equilibration" : 1, + "global_green_equilibration" : true, "dcraw_matrix": [ 7830,-2696,-763,-3325,11667,1866,-641,1712,4824 ], // dcp_v8.6 d65 "ranges": { "black": 15, // 15 is BL offset. dcraw/RT read the base BL from Exif and calculates total BL = BLbase+BLoffset @@ -1711,7 +1711,7 @@ Camera constants: { // Quality B, "make_model": [ "Panasonic DMC-FZ2500", "Panasonic DMC-FZ2000", "Panasonic DMC-FZH1" ], - "global_green_equilibration" : 1, + "global_green_equilibration" : true, "dcraw_matrix": [ 7386,-2443,-743,-3437,11864,1757,-608,1660,4766 ], // dcp_v9.8 d65 "ranges": { "black": 15, // 15 is BL offset. dcraw/RT read the base BL from Exif and calculates total BL = BLbase+BLoffset @@ -1725,7 +1725,7 @@ Camera constants: { // Quality A, samples by helices at RT forums and Chris Power at github "make_model": [ "Panasonic DMC-ZS100", "Panasonic DMC-ZS110", "Panasonic DMC-TZ100", "Panasonic DMC-TZ101", "Panasonic DMC-TZ110", "Panasonic DMC-TX1" ], - "global_green_equilibration" : 1, + "global_green_equilibration" : true, "dcraw_matrix": [ 7790,-2736,-755,-3452,11870,1769,-628,1647,4898 ], // dcp_v8.6 d65 "raw_crop": [ 4, 4, -4, -4 ], // full raw frame 5488x3664 Exif crop 5472X3648 with 8pixel borders. Set the borders at 4 pixels which added with RT's 4 pixels border gives exactly the official frame. "ranges": { @@ -1740,14 +1740,14 @@ Camera constants: { // Quality A "make_model": [ "Panasonic DMC-LF1", "Leica C (Typ 112)" ], - "global_green_equilibration" : 1, + "global_green_equilibration" : true, "dcraw_matrix": [ 9379,-3267,-816,-3227,11560,1881,-926,1928,5340 ], "ranges": { "black": 15, "white": 4050 } // 15 is BL offset. dcraw/RT read the base offset from Exif and calculates total BL = BLbase+BLoffset }, { // Quality A "make_model": [ "Panasonic DMC-TZ60", "Panasonic DMC-TZ61", "Panasonic DMC-ZS40", "Panasonic DMC-ZS41" ], - "global_green_equilibration" : 1, + "global_green_equilibration" : true, "dcraw_matrix": [ 8607,-2822,-808,-3755,11930,2049,-820,2060,5224 ], // matrix from Adobe dcp v8.4 "raw_crop": [ 8, 8, -8, -8 ], // crop according to Exif 4896 X 3672 plus 4 pixels borders. RT's frame gets smaller than dcraw but works better with auto distortion "ranges": { "black": 14, "white": 4050 } // 15 is BL offset. dcraw/RT read the base offset from Exif and calculates total BL = BLbase+BLoffset @@ -1755,7 +1755,7 @@ Camera constants: { // Quality B "make_model": [ "Panasonic DMC-TZ70", "Panasonic DMC-TZ71", "Panasonic DMC-ZS50", "Panasonic DMC-ZS51" ], - "global_green_equilibration" : 1, + "global_green_equilibration" : true, "dcraw_matrix": [ 8802,-3135,-789,-3151,11468,1904,-550,1745,4810 ], // DNG_V8.8 D65 "raw_crop": [ 0, 0, -4, -4 ], // full raw 4/3 4144x3016 8,8,3008,4008 = 4000X3000. RT's frame gets smaller than dcraw but works better with auto distortion "ranges": { "black": 14, "white": 4050 } // 12+1+1 is BL offset @@ -1763,7 +1763,7 @@ Camera constants: { // Quality A, samples by Hombre "make_model": [ "Panasonic DC-ZS70", "Panasonic DC-TZ90", "Panasonic DC-TZ91", "Panasonic DC-TZ92", "Panasonic DC-TZ93" ], - "global_green_equilibration" : 1, + "global_green_equilibration" : true, "dcraw_matrix": [ 9052,-3117,-883,-3045,11346,1927,-205,1520,4730 ], // DNG_V9.10.1 D65 "raw_crop": [ 0, 6, -8, -2 ], // fullraw4/3 5264x3904 official 8,8,3896,5192 = 5184X3888. Dcraw 0,0,5200,3904 RT's frame gets smaller than dcraw but works better with auto distortion "ranges": { "black": 16, "white": 4050 } // 12+3+1 is BL offset @@ -1773,7 +1773,7 @@ Camera constants: { // Quality A, Replicated from rawimage.cc "make_model": [ "Panasonic DMC-G10", "Panasonic DMC-G2" ], - "global_green_equilibration" : 1, + "global_green_equilibration" : true, "dcraw_matrix": [ 8310,-1811,-960,-4941,12990,2151,-1378,2468,6860 ], // Colin Walker "ranges": { "black": 15, // 15 is black offset, dcraw/RT read the base black from Exif and calculates total BL = BLbase+BLoffset @@ -1786,7 +1786,7 @@ Camera constants: { // Quality A, Replicated from rawimage.cc "make_model": "Panasonic DMC-G1", - "global_green_equilibration" : 1, + "global_green_equilibration" : true, "dcraw_matrix": [ 7477,-1615,-651,-5016,12769,2506,-1380,2475,7240 ], // Colin Walker "ranges": { "black": 15, // 15 is BL offset. dcraw/RT read the base black from Exif and calculates total BL = BLbase+BLoffset @@ -1799,7 +1799,7 @@ Camera constants: { // Quality A, Replicated from rawimage.cc "make_model": "Panasonic DMC-G3", - "global_green_equilibration" : 1, + "global_green_equilibration" : true, "dcraw_matrix": [ 6051,-1406,-671,-4015,11505,2868,-1654,2667,6219 ], // Colin Walker "ranges": { "black": 15, // 15 is BL offset. dcraw/RT read the base black from Exif and calculates total BL = BLbase+BLoffset @@ -1808,7 +1808,7 @@ Camera constants: { // Quality A, Replicated from rawimage.cc "make_model": "Panasonic DMC-G5", - "global_green_equilibration" : 1, + "global_green_equilibration" : true, "dcraw_matrix": [ 7122,-2092,-419,-4643,11769,3283,-1363,2413,5944 ], // RT "ranges": { "black": 15, // 15 is BL offset. dcraw/RT read the base black from Exif and calculates total BL = BLbase+BLoffset @@ -1817,7 +1817,7 @@ Camera constants: { // Quality A, Replicated from rawimage.cc "make_model": "Panasonic DMC-GF1", - "global_green_equilibration" : 1, + "global_green_equilibration" : true, "dcraw_matrix": [ 7863,-2080,-668,-4623,12331,2578,-1020,2066,7266 ], // Colin Walker "ranges": { "black": 15, // 15 is BL offset. dcraw/RT read the base black from Exif and calculates total BL = BLbase+BLoffset @@ -1830,7 +1830,7 @@ Camera constants: { // Quality A, Replicated from rawimage.cc "make_model": "Panasonic DMC-GF2", - "global_green_equilibration" : 1, + "global_green_equilibration" : true, "dcraw_matrix": [ 7694,-1791,-745,-4917,12818,2332,-1221,2322,7197 ], // Colin Walker "ranges": { "black": 15, // 15 is BL offset. dcraw/RT read the base black from Exif and calculates total BL = BLbase+BLoffset @@ -1839,7 +1839,7 @@ Camera constants: { // Quality A, Replicated from rawimage.cc "make_model": "Panasonic DMC-GF3", - "global_green_equilibration" : 1, + "global_green_equilibration" : true, "dcraw_matrix": [ 8074,-1846,-861,-5026,12999,2239,-1320,2375,7422 ], // Colin Walker "ranges": { "black": 15, // 15 is BL offset. dcraw/RT read the base black from Exif and calculates total BL = BLbase+BLoffset @@ -1848,7 +1848,7 @@ Camera constants: { // Quality A, Replicated from rawimage.cc "make_model": "Panasonic DMC-GH1", - "global_green_equilibration" : 1, + "global_green_equilibration" : true, "dcraw_matrix": [ 6360,-1557,-375,-4201,11504,3086,-1378,2518,5843 ], // Colin Walker "ranges": { "black": 15, // 15 is BL offset. dcraw/RT read the base black from Exif and calculates total BL = BLbase+BLoffset @@ -1861,7 +1861,7 @@ Camera constants: { // Quality A, Replicated from rawimage.cc "make_model": "Panasonic DMC-GH2", - "global_green_equilibration" : 1, + "global_green_equilibration" : true, //"dcraw_matrix": [ 6855,-1765,-456,-4223,11600,2996,-1450,2602,5761 ], // Colin Walker - disabled due to problems with underwater "dcraw_matrix": [ 7780,-2410,-806,-3913,11724,2484,-1018,2390,5298 ], // dcraw d65 "ranges": { @@ -1875,7 +1875,7 @@ Camera constants: { // Quality B, variable WL "make_model": "Panasonic DMC-GH3", - "global_green_equilibration" : 1, + "global_green_equilibration" : true, "dcraw_matrix": [ 6559,-1752,-491,-3672,11407,2586,-962,1875,5130 ], // dcp d65 "ranges": { "black": 16, // 16 is BL offset. dcraw/RT read the base black from Exif and calculates total BL = BLbase+BLoffset @@ -1888,7 +1888,7 @@ Camera constants: { // Quality B, some ISO WLevels are safely guessed "make_model": "Panasonic DMC-GH4", - "global_green_equilibration" : 1, + "global_green_equilibration" : true, "dcraw_matrix": [ 7122,-2108,-512,-3155,11201,2231,-541,1423,5045 ], // dng_v8.5 d65 "ranges": { "black": 16, // 16 is BL offset. dcraw/RT read the base black from Exif and calculates total BL = BLbase+BLoffset @@ -1902,7 +1902,7 @@ Camera constants: { // Quality C "make_model": "Panasonic DC-GH5", - "global_green_equilibration" : 1, + "global_green_equilibration" : true, "dcraw_matrix": [ 7641,-2336,-605,-3218,11299,2187,-485,1338,5121 ], // DNG_v9.9 D65 "ranges": { "black": 15, // 16 is BL offset. dcraw/RT read the base BL from Exif and calculates total BL = BLbase+BLoffset @@ -1916,7 +1916,7 @@ Camera constants: { // Quality A "make_model": "Panasonic DMC-GM1", - "global_green_equilibration" : 1, + "global_green_equilibration" : true, "dcraw_matrix": [ 6770,-1895,-744,-5232,13145,2303,-1664,2691,5703 ], "ranges": { "black": 15, // 15 is BL offset. dcraw/RT read the base black from Exif and calculates total BL = BLbase+BLoffset @@ -1930,7 +1930,7 @@ Camera constants: { // Quality B, uncertainty about ISO100 WL "make_model": "Panasonic DMC-GM5", - "global_green_equilibration" : 1, + "global_green_equilibration" : true, "dcraw_matrix": [ 8238,-3244,-679,-3921,11814,2384,-836,2022,5852 ], // dng_v8.7 d65 "ranges": { "black": 15, // 15 is BL offset. dcraw/RT read the base black from Exif and calculates total BL = BLbase+BLoffset @@ -1943,7 +1943,7 @@ Camera constants: { // Quality A "make_model": [ "Panasonic DMC-GX7", "Panasonic DMC-GF7", "Panasonic DMC-GF8" ], - "global_green_equilibration" : 1, + "global_green_equilibration" : true, "dcraw_matrix": [ 7610,-2780,-576,-4614,12195,2733,-1375,2393,6490 ], "ranges": { "black": 15, // 15 is BL offset. dcraw/RT read the base black from Exif and calculates total BL = BLbase+BLoffset @@ -1957,7 +1957,7 @@ Camera constants: { // Quality A "make_model": [ "Panasonic DMC-G7", "Panasonic DMC-G70" ], - "global_green_equilibration" : 1, + "global_green_equilibration" : true, "dcraw_matrix": [ 7610,-2780,-576,-4614,12195,2733,-1375,2393,6490 ], // DNG_v9.1 D65 "ranges": { "black": 16, // 16 is BL offset. dcraw/RT read the base black from Exif and calculates total BL = BLbase+BLoffset @@ -1971,7 +1971,7 @@ Camera constants: { // Quality B "make_model": [ "Panasonic DMC-GX80", "Panasonic DMC-GX85", "Panasonic DMC-GX7MK2" ], - "global_green_equilibration" : 1, + "global_green_equilibration" : true, "dcraw_matrix": [ 7771,-3020,-629,-4029,11950,2345,-821,1977,6119 ], // DNG_v9.6 D65 "ranges": { "black": 16, // 16 is BL offset. dcraw/RT read the base black from Exif and calculates total BL = BLbase+BLoffset @@ -1985,7 +1985,7 @@ Camera constants: { // Quality X, no white-frames nor black-frames yet, see #4550 "make_model": [ "Panasonic DC-GX9" ], - "global_green_equilibration" : 1, + "global_green_equilibration" : true, "dcraw_matrix": [ 7564,-2263,-606,-3148,11239,2177,-540,1435,4853 ], // ColorMatrix2 from Adobe DNG Converter 10.3 "ranges": { "black": 16, @@ -1995,7 +1995,7 @@ Camera constants: { // Quality B, Same as Panasonic G7 "make_model": [ "Panasonic DMC-G8", "Panasonic DMC-G80", "Panasonic DMC-G81", "Panasonic DMC-G85" ], - "global_green_equilibration" : 1, + "global_green_equilibration" : true, "dcraw_matrix": [ 7610,-2780,-576,-4614,12195,2733,-1375,2393,6490 ], // DNG_v9.7 D65 "ranges": { "black": 16, // 16 is BL offset. dcraw/RT read the base black from Exif and calculates total BL = BLbase+BLoffset @@ -2009,7 +2009,7 @@ Camera constants: { // Quality B "make_model": "Panasonic DMC-GX8", - "global_green_equilibration" : 1, + "global_green_equilibration" : true, "dcraw_matrix": [ 7564,-2263,-606,-3148,11239,2177,-540,1435,4853 ], // DNG_v9.1.1 D65 "ranges": { "black": 15, // 16 is BL offset. dcraw/RT read the base BL from Exif and calculates total BL = BLbase+BLoffset @@ -2023,7 +2023,7 @@ Camera constants: { // Quality B, samples by Ingo, missing some long exposure at high ISO samples with LENR ON "make_model": [ "Panasonic DMC-LX100", "Leica D-LUX (Typ 109)" ], - "global_green_equilibration" : 1, + "global_green_equilibration" : true, "dcraw_matrix": [ 8844,-3538,-768,-3709,11762,2200,-698,1792,5220 ], // DNG_V8.7 d65 //"dcraw_matrix": [ 6538,-1614,-549,-5475,13096,2646,-1780,2799,5612 ], // calculated from DxO D50 "ranges": { @@ -2044,7 +2044,7 @@ Camera constants: { // Quality B, Intermediate ISOs missing "make_model": [ "Panasonic DMC-LX9", "Panasonic DMC-LX10", "Panasonic DMC-LX15" ], - "global_green_equilibration" : 1, + "global_green_equilibration" : true, "dcraw_matrix": [ 7790,-2736,-755,-3452,11870,1769,-628,1647,4898 ], // DNg_v9.8 d65 "raw_crop": [ 4, 4, -4, -4 ], // full raw frame 5488x3664 Exif crop 5472X3648 with 8pixel borders. Set the borders at 4 pixels which added with RT's 4 pixels border gives exactly the official frame. "ranges": { diff --git a/rtengine/rawimagesource.cc b/rtengine/rawimagesource.cc index 0c35154bf..5438b8b1e 100644 --- a/rtengine/rawimagesource.cc +++ b/rtengine/rawimagesource.cc @@ -1956,6 +1956,9 @@ void RawImageSource::preprocess (const RAWParams &raw, const LensProfParams &le }; if ( ri->getSensorType() == ST_BAYER && (raw.bayersensor.greenthresh || (globalGreenEq() && raw.bayersensor.method != RAWParams::BayerSensor::getMethodString( RAWParams::BayerSensor::Method::VNG4))) ) { + if (settings->verbose) { + printf("Performing global green equilibration...\n"); + } // global correction if(numFrames == 4) { for(int i = 0; i < 4; ++i) { From 6a317ee4fc29e89e5b5743cdc047f9aede0def3d Mon Sep 17 00:00:00 2001 From: heckflosse Date: Fri, 8 Jun 2018 16:04:25 +0200 Subject: [PATCH 29/42] Fix broken clang build --- rtengine/pixelshift.cc | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/rtengine/pixelshift.cc b/rtengine/pixelshift.cc index 248336407..174c02065 100644 --- a/rtengine/pixelshift.cc +++ b/rtengine/pixelshift.cc @@ -323,9 +323,9 @@ BENCHFUN if(motionDetection) { if(!showOnlyMask) { if(bayerParams.pixelShiftMedian) { // We need the demosaiced frames for motion correction - if (bayerParams.pixelShiftDemosaicMethod == bayerParams.getPSDemosaicMethodString(bayerParams.PSDemosaicMethod::LMMSE)) { + 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(bayerParams.PSDemosaicMethod::AMAZEVNG4)) { + } else if (bayerParams.pixelShiftDemosaicMethod == bayerParams.getPSDemosaicMethodString(RAWParams::BayerSensor::PSDemosaicMethod::AMAZEVNG4)) { amaze_vng4_demosaic_RT (winw, winh, *(rawDataFrames[0]), red, green, blue, bayerParams.dualDemosaicContrast); } else { amaze_demosaic_RT(winx, winy, winw, winh, *(rawDataFrames[0]), red, green, blue); @@ -335,9 +335,9 @@ BENCHFUN multi_array2D blueTmp(winw, winh); for(int i = 0; i < 3; i++) { - if (bayerParams.pixelShiftDemosaicMethod == bayerParams.getPSDemosaicMethodString(bayerParams.PSDemosaicMethod::LMMSE)) { + 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(bayerParams.PSDemosaicMethod::AMAZEVNG4)) { + } else if (bayerParams.pixelShiftDemosaicMethod == bayerParams.getPSDemosaicMethodString(RAWParams::BayerSensor::PSDemosaicMethod::AMAZEVNG4)) { amaze_vng4_demosaic_RT (winw, winh, *(rawDataFrames[i + 1]), redTmp[i], greenTmp[i], blueTmp[i], bayerParams.dualDemosaicContrast); } else { amaze_demosaic_RT(winx, winy, winw, winh, *(rawDataFrames[i + 1]), redTmp[i], greenTmp[i], blueTmp[i]); @@ -362,9 +362,9 @@ BENCHFUN } } } else { - if (bayerParams.pixelShiftDemosaicMethod == bayerParams.getPSDemosaicMethodString(bayerParams.PSDemosaicMethod::LMMSE)) { + if (bayerParams.pixelShiftDemosaicMethod == bayerParams.getPSDemosaicMethodString(RAWParams::BayerSensor::PSDemosaicMethod::LMMSE)) { lmmse_interpolate_omp(winw, winh, rawData, red, green, blue, bayerParams.lmmse_iterations); - } else if (bayerParams.pixelShiftDemosaicMethod == bayerParams.getPSDemosaicMethodString(bayerParams.PSDemosaicMethod::AMAZEVNG4)) { + } else if (bayerParams.pixelShiftDemosaicMethod == bayerParams.getPSDemosaicMethodString(RAWParams::BayerSensor::PSDemosaicMethod::AMAZEVNG4)) { amaze_vng4_demosaic_RT (winw, winh, rawData, red, green, blue, bayerParams.dualDemosaicContrast); } else { amaze_demosaic_RT(winx, winy, winw, winh, rawData, red, green, blue); From 039f68e545af7cd6884111327fc859552818f2c2 Mon Sep 17 00:00:00 2001 From: heckflosse Date: Fri, 8 Jun 2018 17:48:53 +0200 Subject: [PATCH 30/42] Fix another two bugs I introduced --- rtengine/procparams.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rtengine/procparams.cc b/rtengine/procparams.cc index 9f6f26cf5..00419693c 100644 --- a/rtengine/procparams.cc +++ b/rtengine/procparams.cc @@ -4711,9 +4711,9 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited) if (keyFile.has_key("RAW Bayer", "pixelShiftLmmse")) { bool useLmmse = keyFile.get_boolean ("RAW Bayer", "pixelShiftLmmse"); if (useLmmse) { - raw.bayersensor.pixelShiftDemosaicMethod = raw.bayersensor.getPSDemosaicMethodString(raw.bayersensor.PSDemosaicMethod::LMMSE); + raw.bayersensor.pixelShiftDemosaicMethod = raw.bayersensor.getPSDemosaicMethodString(RAWParams::BayerSensor::PSDemosaicMethod::LMMSE); } else { - raw.bayersensor.pixelShiftDemosaicMethod = raw.bayersensor.getPSDemosaicMethodString(raw.bayersensor.PSDemosaicMethod::AMAZE); + raw.bayersensor.pixelShiftDemosaicMethod = raw.bayersensor.getPSDemosaicMethodString(RAWParams::BayerSensor::PSDemosaicMethod::AMAZE); } if (pedited) { pedited->raw.bayersensor.pixelShiftDemosaicMethod = true; From 44729edf0417e4d652dbe19a9f94ffa0edb93b48 Mon Sep 17 00:00:00 2001 From: heckflosse Date: Sun, 10 Jun 2018 14:35:12 +0200 Subject: [PATCH 31/42] Prepared engine to display the Sharpening Contrast mask --- rtdata/languages/default | 1 + rtengine/dcrop.cc | 4 ++-- rtengine/improccoordinator.cc | 7 +++++- rtengine/improccoordinator.h | 3 ++- rtengine/improcfun.cc | 5 +++-- rtengine/improcfun.h | 7 +++--- rtengine/ipsharpen.cc | 41 ++++++++++++++++++++++++++++++++--- rtengine/rtengine.h | 1 + rtgui/indclippedpanel.cc | 38 +++++++++++++++++++++++++++++--- rtgui/indclippedpanel.h | 7 ++++-- 10 files changed, 97 insertions(+), 17 deletions(-) diff --git a/rtdata/languages/default b/rtdata/languages/default index d7653a230..590c59478 100644 --- a/rtdata/languages/default +++ b/rtdata/languages/default @@ -857,6 +857,7 @@ MAIN_TOOLTIP_INDCLIPPEDH;Clipped highlight indication.\nShortcut: < MAIN_TOOLTIP_INDCLIPPEDS;Clipped shadow indication.\nShortcut: > MAIN_TOOLTIP_PREVIEWB;Preview the Blue channel.\nShortcut: b MAIN_TOOLTIP_PREVIEWFOCUSMASK;Preview the Focus Mask.\nShortcut: Shift-f\n\nMore accurate on images with shallow depth of field, low noise and at higher zoom levels.\n\nTo improve detection accuracy for noisy images evaluate at smaller zoom, about 10-30%. +MAIN_TOOLTIP_PREVIEWSHARPMASK;Preview the Sharpening Contrast Mask.\nShortcut: None\n\nOnly works when sharpening is enabled and zoom >= 100% MAIN_TOOLTIP_PREVIEWG;Preview the Green channel.\nShortcut: g MAIN_TOOLTIP_PREVIEWL;Preview the Luminosity.\nShortcut: v\n\n0.299*R + 0.587*G + 0.114*B MAIN_TOOLTIP_PREVIEWR;Preview the Red channel.\nShortcut: r diff --git a/rtengine/dcrop.cc b/rtengine/dcrop.cc index e2b4d2002..99aeccbe8 100644 --- a/rtengine/dcrop.cc +++ b/rtengine/dcrop.cc @@ -865,7 +865,7 @@ void Crop::update (int todo) if ((params.colorappearance.enabled && !settings->autocielab) || (!params.colorappearance.enabled)) { parent->ipf.MLmicrocontrast (labnCrop); - parent->ipf.sharpening (labnCrop, params.sharpening); + parent->ipf.sharpening (labnCrop, params.sharpening, parent->sharpMask); } } @@ -994,7 +994,7 @@ void Crop::update (int todo) float d, dj, yb; // not used after this block parent->ipf.ciecam_02float (cieCrop, float (adap), 1, 2, labnCrop, ¶ms, parent->customColCurve1, parent->customColCurve2, parent->customColCurve3, - dummy, dummy, parent->CAMBrightCurveJ, parent->CAMBrightCurveQ, parent->CAMMean, 5, skip, execsharp, d, dj, yb, 1); + dummy, dummy, parent->CAMBrightCurveJ, parent->CAMBrightCurveQ, parent->CAMMean, 5, skip, execsharp, d, dj, yb, 1, parent->sharpMask); } else { // CIECAM is disabled, we free up its image buffer to save some space if (cieCrop) { diff --git a/rtengine/improccoordinator.cc b/rtengine/improccoordinator.cc index f39fe3415..714ad2b41 100644 --- a/rtengine/improccoordinator.cc +++ b/rtengine/improccoordinator.cc @@ -35,7 +35,7 @@ extern const Settings* settings; ImProcCoordinator::ImProcCoordinator () : orig_prev (nullptr), oprevi (nullptr), oprevl (nullptr), nprevl (nullptr), fattal_11_dcrop_cache(nullptr), previmg (nullptr), workimg (nullptr), ncie (nullptr), imgsrc (nullptr), lastAwbEqual (0.), lastAwbTempBias (0.0), ipf (¶ms, true), monitorIntent (RI_RELATIVE), - softProof (false), gamutCheck (false), scale (10), highDetailPreprocessComputed (false), highDetailRawComputed (false), + softProof (false), gamutCheck (false), sharpMask(false), scale (10), highDetailPreprocessComputed (false), highDetailRawComputed (false), allocated (false), bwAutoR (-9000.f), bwAutoG (-9000.f), bwAutoB (-9000.f), CAMMean (NAN), hltonecurve (65536), @@ -1160,6 +1160,11 @@ void ImProcCoordinator::getSoftProofing (bool &softProof, bool &gamutCheck) gamutCheck = this->gamutCheck; } +void ImProcCoordinator::setSharpMask (bool sharpMask) +{ + this->sharpMask = sharpMask; +} + void ImProcCoordinator::saveInputICCReference (const Glib::ustring& fname, bool apply_wb) { diff --git a/rtengine/improccoordinator.h b/rtengine/improccoordinator.h index ada7ed754..aabc9000b 100644 --- a/rtengine/improccoordinator.h +++ b/rtengine/improccoordinator.h @@ -76,6 +76,7 @@ protected: RenderingIntent monitorIntent; bool softProof; bool gamutCheck; + bool sharpMask; int scale; bool highDetailPreprocessComputed; @@ -271,7 +272,7 @@ public: void getMonitorProfile (Glib::ustring& profile, RenderingIntent& intent) const; void setSoftProofing (bool softProof, bool gamutCheck); void getSoftProofing (bool &softProof, bool &gamutCheck); - + void setSharpMask (bool sharpMask); bool updateTryLock () { return updaterThreadStart.trylock(); diff --git a/rtengine/improcfun.cc b/rtengine/improcfun.cc index 5aea884fb..b5b4e1d13 100644 --- a/rtengine/improcfun.cc +++ b/rtengine/improcfun.cc @@ -462,7 +462,8 @@ void ImProcFunctions::firstAnalysis (const Imagefloat* const original, const Pro // Copyright (c) 2012 Jacques Desmis void ImProcFunctions::ciecam_02float (CieImage* ncie, float adap, int pW, int pwb, LabImage* lab, const ProcParams* params, const ColorAppearance & customColCurve1, const ColorAppearance & customColCurve2, const ColorAppearance & customColCurve3, - LUTu & histLCAM, LUTu & histCCAM, LUTf & CAMBrightCurveJ, LUTf & CAMBrightCurveQ, float &mean, int Iterates, int scale, bool execsharp, float &d, float &dj, float &yb, int rtt) + LUTu & histLCAM, LUTu & histCCAM, LUTf & CAMBrightCurveJ, LUTf & CAMBrightCurveQ, float &mean, int Iterates, int scale, bool execsharp, float &d, float &dj, float &yb, int rtt, + bool showSharpMask) { if (params->colorappearance.enabled) { @@ -1675,7 +1676,7 @@ void ImProcFunctions::ciecam_02float (CieImage* ncie, float adap, int pW, int pw if (params->sharpening.enabled) if (execsharp) { float **buffer = lab->L; // We can use the L-buffer from lab as buffer to save some memory - ImProcFunctions::sharpeningcam (ncie, buffer); // sharpening adapted to CIECAM + ImProcFunctions::sharpeningcam (ncie, buffer, showSharpMask); // sharpening adapted to CIECAM } //if(params->dirpyrequalizer.enabled) if(execsharp) { diff --git a/rtengine/improcfun.h b/rtengine/improcfun.h index 78f0c5b9e..003e09be2 100644 --- a/rtengine/improcfun.h +++ b/rtengine/improcfun.h @@ -222,12 +222,13 @@ public: void luminanceCurve (LabImage* lold, LabImage* lnew, LUTf &curve); void ciecam_02float (CieImage* ncie, float adap, int pW, int pwb, LabImage* lab, const ProcParams* params, const ColorAppearance & customColCurve1, const ColorAppearance & customColCurve, const ColorAppearance & customColCurve3, - LUTu &histLCAM, LUTu &histCCAM, LUTf & CAMBrightCurveJ, LUTf & CAMBrightCurveQ, float &mean, int Iterates, int scale, bool execsharp, float &d, float &dj, float &yb, int rtt); + LUTu &histLCAM, LUTu &histCCAM, LUTf & CAMBrightCurveJ, LUTf & CAMBrightCurveQ, float &mean, int Iterates, int scale, bool execsharp, float &d, float &dj, float &yb, int rtt, + bool showSharpMask = false); void chromiLuminanceCurve (PipetteBuffer *pipetteBuffer, int pW, LabImage* lold, LabImage* lnew, LUTf &acurve, LUTf &bcurve, LUTf & satcurve, LUTf & satclcurve, LUTf &clcurve, LUTf &curve, bool utili, bool autili, bool butili, bool ccutili, bool cclutili, bool clcutili, LUTu &histCCurve, LUTu &histLurve); void vibrance (LabImage* lab);//Jacques' vibrance // void colorCurve (LabImage* lold, LabImage* lnew); - void sharpening (LabImage* lab, const SharpeningParams &sharpenParam); - void sharpeningcam (CieImage* ncie, float** buffer); + void sharpening (LabImage* lab, const SharpeningParams &sharpenParam, bool showMask = false); + void sharpeningcam (CieImage* ncie, float** buffer, bool showMask = false); void transform (Imagefloat* original, Imagefloat* transformed, int cx, int cy, int sx, int sy, int oW, int oH, int fW, int fH, const FramesMetaData *metadata, int rawRotationDeg, bool fullImage); float resizeScale (const ProcParams* params, int fw, int fh, int &imw, int &imh); void lab2monitorRgb (LabImage* lab, Image8* image); diff --git a/rtengine/ipsharpen.cc b/rtengine/ipsharpen.cc index 855a8a8c9..6387cfde5 100644 --- a/rtengine/ipsharpen.cc +++ b/rtengine/ipsharpen.cc @@ -220,7 +220,7 @@ BENCHFUN } // end parallel } -void ImProcFunctions::sharpening (LabImage* lab, const SharpeningParams &sharpenParam) +void ImProcFunctions::sharpening (LabImage* lab, const SharpeningParams &sharpenParam, bool showMask) { if ((!sharpenParam.enabled) || sharpenParam.amount < 1 || lab->W < 8 || lab->H < 8) { @@ -228,6 +228,23 @@ void ImProcFunctions::sharpening (LabImage* lab, const SharpeningParams &sharpen } int W = lab->W, H = lab->H; + + if(showMask) { + // calculate contrast based blend factors to reduce sharpening in regions with low contrast + JaggedArray blend(W, H); + buildBlendMask(lab->L, blend, W, H, sharpenParam.contrast / 100.f); +#ifdef _OPENMP + #pragma omp parallel for +#endif + + for (int i = 0; i < H; ++i) { + for (int j = 0; j < W; ++j) { + lab->L[i][j] = blend[i][j] * 32768.f; + } + } + return; + } + JaggedArray b2(W, H); if (sharpenParam.method == "rld") { @@ -801,12 +818,31 @@ void ImProcFunctions::MLmicrocontrastcam(CieImage* ncie) MLmicrocontrast(ncie->sh_p, ncie->W, ncie->H); } -void ImProcFunctions::sharpeningcam (CieImage* ncie, float** b2) +void ImProcFunctions::sharpeningcam (CieImage* ncie, float** b2, bool showMask) { if ((!params->sharpening.enabled) || params->sharpening.amount < 1 || ncie->W < 8 || ncie->H < 8) { return; } + int W = ncie->W, H = ncie->H; + + if(showMask) { + // calculate contrast based blend factors to reduce sharpening in regions with low contrast + JaggedArray blend(W, H); + buildBlendMask(ncie->sh_p, blend, W, H, params->sharpening.contrast / 100.f); +#ifdef _OPENMP + #pragma omp parallel for +#endif + + for (int i = 0; i < H; ++i) { + for (int j = 0; j < W; ++j) { + ncie->sh_p[i][j] = blend[i][j] * 32768.f; + } + } + return; + } + + if (params->sharpening.method == "rld") { deconvsharpening (ncie->sh_p, b2, ncie->W, ncie->H, params->sharpening); return; @@ -814,7 +850,6 @@ void ImProcFunctions::sharpeningcam (CieImage* ncie, float** b2) // Rest is UNSHARP MASK - int W = ncie->W, H = ncie->H; float** b3 = nullptr; if (params->sharpening.edgesonly) { diff --git a/rtengine/rtengine.h b/rtengine/rtengine.h index f50321775..c76c542e3 100644 --- a/rtengine/rtengine.h +++ b/rtengine/rtengine.h @@ -482,6 +482,7 @@ public: virtual void getMonitorProfile (Glib::ustring& monitorProfile, RenderingIntent& intent) const = 0; virtual void setSoftProofing (bool softProof, bool gamutCheck) = 0; virtual void getSoftProofing (bool &softProof, bool &gamutCheck) = 0; + virtual void setSharpMask (bool sharpMask) = 0; virtual ~StagedImageProcessor () {} diff --git a/rtgui/indclippedpanel.cc b/rtgui/indclippedpanel.cc index ae7cff644..35cfa843d 100644 --- a/rtgui/indclippedpanel.cc +++ b/rtgui/indclippedpanel.cc @@ -27,11 +27,20 @@ IndicateClippedPanel::IndicateClippedPanel (ImageArea* ia) : imageArea(ia) iFon = new RTImage ("previewmodeF-focusScreen-on.png"); iFoff = new RTImage ("previewmodeF-focusScreen-off.png"); + // for previewSharpMask, needs to be replaced with different icons + iSon = new RTImage ("previewmodeF-focusScreen-on.png"); + iSoff = new RTImage ("previewmodeF-focusScreen-off.png"); + previewFocusMask = Gtk::manage (new Gtk::ToggleButton ()); previewFocusMask->set_relief(Gtk::RELIEF_NONE); previewFocusMask->set_tooltip_markup (M("MAIN_TOOLTIP_PREVIEWFOCUSMASK")); previewFocusMask->set_image(*iFoff); + previewSharpMask = Gtk::manage (new Gtk::ToggleButton ()); + previewSharpMask->set_relief(Gtk::RELIEF_NONE); + previewSharpMask->set_tooltip_markup (M("MAIN_TOOLTIP_PREVIEWSHARPMASK")); + previewSharpMask->set_image(*iSoff); + Glib::ustring tt; indClippedH = Gtk::manage (new Gtk::ToggleButton ()); @@ -57,13 +66,16 @@ IndicateClippedPanel::IndicateClippedPanel (ImageArea* ia) : imageArea(ia) } previewFocusMask->set_active (false); + previewSharpMask->set_active (false); indClippedH->set_active (options.showClippedHighlights); indClippedS->set_active (options.showClippedShadows); pack_start (*previewFocusMask, Gtk::PACK_SHRINK, 0); + pack_start (*previewSharpMask, Gtk::PACK_SHRINK, 0); pack_start (*indClippedS, Gtk::PACK_SHRINK, 0); pack_start (*indClippedH, Gtk::PACK_SHRINK, 0); + connSharpMask = previewSharpMask->signal_toggled().connect( sigc::bind(sigc::mem_fun(*this, &IndicateClippedPanel::buttonToggled), previewSharpMask) ); connFocusMask = previewFocusMask->signal_toggled().connect( sigc::bind(sigc::mem_fun(*this, &IndicateClippedPanel::buttonToggled), previewFocusMask) ); connClippedS = indClippedS->signal_toggled().connect( sigc::bind(sigc::mem_fun(*this, &IndicateClippedPanel::buttonToggled), indClippedS) ); connClippedH = indClippedH->signal_toggled().connect( sigc::bind(sigc::mem_fun(*this, &IndicateClippedPanel::buttonToggled), indClippedH) ); @@ -86,27 +98,45 @@ void IndicateClippedPanel::toggleFocusMask () previewFocusMask->set_active(!previewFocusMask->get_active()); } +void IndicateClippedPanel::toggleSharpMask () +{ + previewSharpMask->set_active(!previewSharpMask->get_active()); +} + void IndicateClippedPanel::buttonToggled (Gtk::ToggleButton* tb) { connFocusMask.block(true); + connSharpMask.block(true); connClippedS.block(true); connClippedH.block(true); - if (tb != previewFocusMask) { - previewFocusMask->set_active(false); - } else { + if (tb == previewFocusMask) { if (indClippedS->get_active()) { indClippedS->set_active(false); } if (indClippedH->get_active()) { indClippedH->set_active(false); } + previewSharpMask->set_active(false); + } else if (tb == previewSharpMask) { + if (indClippedS->get_active()) { + indClippedS->set_active(false); + } + if (indClippedH->get_active()) { + indClippedH->set_active(false); + } + previewFocusMask->set_active(false); + } else { + previewFocusMask->set_active(false); + previewSharpMask->set_active(false); } previewFocusMask->set_image(previewFocusMask->get_active() ? *iFon : *iFoff); + previewSharpMask->set_image(previewSharpMask->get_active() ? *iSon : *iSoff); connFocusMask.block(false); + connSharpMask.block(false); connClippedS.block(false); connClippedH.block(false); @@ -123,4 +153,6 @@ IndicateClippedPanel::~IndicateClippedPanel () { delete iFon; delete iFoff; + delete iSon; + delete iSoff; } diff --git a/rtgui/indclippedpanel.h b/rtgui/indclippedpanel.h index 1da4b61de..b4225a9cb 100644 --- a/rtgui/indclippedpanel.h +++ b/rtgui/indclippedpanel.h @@ -19,13 +19,15 @@ #define _INDCLIPPEDPANEL_ #include +#include class ImageArea; class IndicateClippedPanel : public Gtk::HBox { protected: - Gtk::Image* iFon, *iFoff; + Gtk::Image* iFon, *iFoff, *iSon, *iSoff; + Gtk::ToggleButton* previewSharpMask; Gtk::ToggleButton* previewFocusMask; Gtk::ToggleButton* indClippedH; Gtk::ToggleButton* indClippedS; @@ -38,8 +40,9 @@ public: void buttonToggled(Gtk::ToggleButton* tb); void toggleClipped(bool highlights); // inverts a toggle programmatically void toggleFocusMask(); + void toggleSharpMask(); - sigc::connection connFocusMask, connClippedS, connClippedH; + sigc::connection connFocusMask, connSharpMask, connClippedS, connClippedH; bool showFocusMask () From 83e686a719a18d1c05ad0110b282a10a35fef30b Mon Sep 17 00:00:00 2001 From: Morgan Hardwood Date: Mon, 11 Jun 2018 21:52:23 +0200 Subject: [PATCH 32/42] Fixes bugs in Black-and-White tool - Incorrect history messages were shown. - Channel mixer "Auto" behaved incorrectly. Fixes by Jacques Desmis. Closes #4570 --- rtengine/procparams.cc | 2 +- rtgui/blackwhite.cc | 17 ++++++++++++++++- rtgui/blackwhite.h | 1 + 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/rtengine/procparams.cc b/rtengine/procparams.cc index 00419693c..36fa4aa22 100644 --- a/rtengine/procparams.cc +++ b/rtengine/procparams.cc @@ -1842,7 +1842,7 @@ BlackWhiteParams::BlackWhiteParams() : enabledcc(true), enabled(false), filter("None"), - setting("NormalContrast"), + setting("RGB-Rel"), method("Desaturation"), mixerRed(33), mixerOrange(33), diff --git a/rtgui/blackwhite.cc b/rtgui/blackwhite.cc index 6970a2f31..507d3aee6 100644 --- a/rtgui/blackwhite.cc +++ b/rtgui/blackwhite.cc @@ -128,7 +128,7 @@ BlackWhite::BlackWhite (): FoldableToolPanel(this, "blackwhite", M("TP_BWMIX_LAB setting->append (M("TP_BWMIX_SET_ROYGCBPMREL")); setting->append (M("TP_BWMIX_SET_INFRARED")); - setting->set_active (0); + setting->set_active (11); settingHBox->pack_start (*setting); mixerVBox->pack_start (*settingHBox); settingconn = setting->signal_changed().connect ( sigc::mem_fun(*this, &BlackWhite::settingChanged) ); @@ -388,9 +388,21 @@ bool BlackWhite::BWComputed_ () disableListener (); mixerRed->setValue (nextredbw); + adjusterChanged(mixerRed, mixerRed->getValue()); mixerGreen->setValue (nextgreenbw); + adjusterChanged(mixerGreen, mixerGreen->getValue()); mixerBlue->setValue (nextbluebw); + adjusterChanged(mixerBlue, mixerBlue->getValue()); + autoconn.block (true); + autoch->set_active (true); + autoconn.block (false); + lastAuto = false; + nextcount++; enableListener (); + if (listener && nextcount <= 1 ) { + // activated only 1 time, but perhaps in some cases if we want that all is update pp3, auto, sliders : nextcount <= 2 but it cost time and result is identical + listener->panelChanged (EvAutoch, M("GENERAL_ENABLED")); + } updateRGBLabel(); @@ -789,6 +801,7 @@ void BlackWhite::filterChanged () if (listener && (multiImage || getEnabled())) { listener->panelChanged (EvBWfilter, filter->get_active_text ()); + listener->panelChanged (EvAutoch, M("GENERAL_ENABLED")); } } @@ -884,6 +897,7 @@ void BlackWhite::neutral_pressed () updateRGBLabel(); + nextcount = 0; if(listener) { listener->panelChanged (EvNeutralBW, M("GENERAL_RESET")); } @@ -1089,6 +1103,7 @@ void BlackWhite::adjusterChanged (Adjuster* a, double newval) autoch->set_inconsistent (false); } + nextcount = 0; autoconn.block(true); autoch->set_active (false); autoconn.block(false); diff --git a/rtgui/blackwhite.h b/rtgui/blackwhite.h index 5f0ffec44..07ad6a160 100644 --- a/rtgui/blackwhite.h +++ b/rtgui/blackwhite.h @@ -138,6 +138,7 @@ private: double nextredbw; double nextgreenbw; double nextbluebw; + int nextcount = 0; IdleRegister idle_register; }; From 55f232f4dda80caaf22181ea11b928998ade3378 Mon Sep 17 00:00:00 2001 From: Alberto Griggio Date: Tue, 12 Jun 2018 08:44:34 +0200 Subject: [PATCH 33/42] updated camconst.json with global green eq info according to iliasg's advice --- rtengine/camconst.json | 41 +++++------------------------------------ 1 file changed, 5 insertions(+), 36 deletions(-) diff --git a/rtengine/camconst.json b/rtengine/camconst.json index bfa22567c..449484e8a 100644 --- a/rtengine/camconst.json +++ b/rtengine/camconst.json @@ -1563,7 +1563,6 @@ Camera constants: { // Quality B, 16Mp and 64Mp raw frames "make_model": "OLYMPUS E-M5MarkII", - "global_green_equilibration" : true, "dcraw_matrix": [ 9422,-3258,-711,-2655,10898,2015,-512,1354,5512 ], // DNG_v8.8 D65 "raw_crop": [ 0, 0, -6, -6 ], // largest valid, full 64Mp 9280x6938, official crop 0 0 9216 6912 "ranges": { @@ -1612,7 +1611,6 @@ Camera constants: { // Quality B, crop correction "make_model": [ "OLYMPUS E-M10", "OLYMPUS E-M10MarkII", "OLYMPUS E-M10 Mark III" ], - "global_green_equilibration" : true, "dcraw_matrix": [ 8380,-2630,-639,-2887,10725,2496,-627,1427,5438 ], "raw_crop": [ 0, 0, 4624, 3472 ], // largest valid - full frame is 4640x3472 //"raw_crop": [ 4, 4, 4616, 3464 ], // olympus jpeg crop 8, 8, 4608, 3456 @@ -1645,9 +1643,13 @@ Camera constants: "ranges": { "white": 4050 } // safe for worst case detected, nominal is 4093 }, + { // Quality C, only green equilibration + "make_model" : ["OLYMPUS E-3", "OLYMPUS E-520"], + "global_green_equilibration" : true + }, + { // Quality C, proper ISO 100-125-160 samples missing, pixelshift files have no black offset etc. #4574 "make_model": [ "Panasonic DC-G9" ], - "global_green_equilibration" : true, "dcraw_matrix": [ 7685, -2375, -634, -3687, 11700, 2249, -748, 1546, 5111 ], // Adobe DNG Converter 10.3 ColorMatrix2 "ranges": { "black": 15, // 15 is BL offset. dcraw/RT reads the base black from Exif and calculates total BL = BLbase+BLoffset @@ -1661,7 +1663,6 @@ Camera constants: { // Quality B, CameraPhone, some samples are missing but has the same sensor as FZ1000 .. "make_model": [ "Panasonic DMC-CM1", "Panasonic DMC-CM10" ], - "global_green_equilibration" : true, "dcraw_matrix": [ 8770,-3194,-820,-2871,11281,1803,-513,1552,4434 ], // dcp_v8.7 d65 "ranges": { "black": 15, // 15 is BL offset. dcraw/RT read the base BL from Exif and calculates total BL = BLbase+BLoffset @@ -1675,7 +1676,6 @@ Camera constants: { // Quality B "make_model": [ "Panasonic DC-FZ80", "Panasonic DC-FZ81", "Panasonic DC-FZ82", "Panasonic DC-FZ83" ], - "global_green_equilibration" : true, "dcraw_matrix": [ 8550,-2908,-842,-3195,11529,1881,-338,1603,4631 ], // DNGv9.10.1 D65 "raw_crop": [ 0, 6, -8, -2 ], // fullraw4/3 5040x3688 official 8,8,4904,3680 = 4896X3672. Dcraw 0,0,4912,3688 RT's frame gets smaller than dcraw but works better with auto distortion "ranges": { "black": 15, "white": 4050 } // 15 is BL offset. dcraw/RT read the base offset from Exif and calculates total BL = BLbase+BLoffset @@ -1683,21 +1683,18 @@ Camera constants: { // Quality A, replicated from rawimage.cc "make_model": "Panasonic DMC-FZ150", - "global_green_equilibration" : true, "dcraw_matrix": [ 10435,-3208,-72,-2293,10506,2067,-486,1725,4682 ], // RT, copy from custom dcp d55 "ranges": { "black": 15, "white": 4050 } // 15 is BL offset. dcraw/RT read the base offset from Exif and calculates total BL = BLbase+BLoffset }, { // Quality B, "make_model": [ "Panasonic DMC-FZ300", "Panasonic DMC-FZ330" ], - "global_green_equilibration" : true, "dcraw_matrix": [ 8378,-2798,-769,-3068,11410,1877,-538,1792,4623 ], // DNG-V9.1.1 "ranges": { "black": 15, "white": 4050 } // 15 is BL offset. dcraw/RT read the base offset from Exif and calculates total BL = BLbase+BLoffset }, { // Quality A, samples by helices at RT forums "make_model": [ "Panasonic DMC-FZ1000", "Leica V-LUX (Typ 114)" ], - "global_green_equilibration" : true, "dcraw_matrix": [ 7830,-2696,-763,-3325,11667,1866,-641,1712,4824 ], // dcp_v8.6 d65 "ranges": { "black": 15, // 15 is BL offset. dcraw/RT read the base BL from Exif and calculates total BL = BLbase+BLoffset @@ -1711,7 +1708,6 @@ Camera constants: { // Quality B, "make_model": [ "Panasonic DMC-FZ2500", "Panasonic DMC-FZ2000", "Panasonic DMC-FZH1" ], - "global_green_equilibration" : true, "dcraw_matrix": [ 7386,-2443,-743,-3437,11864,1757,-608,1660,4766 ], // dcp_v9.8 d65 "ranges": { "black": 15, // 15 is BL offset. dcraw/RT read the base BL from Exif and calculates total BL = BLbase+BLoffset @@ -1725,7 +1721,6 @@ Camera constants: { // Quality A, samples by helices at RT forums and Chris Power at github "make_model": [ "Panasonic DMC-ZS100", "Panasonic DMC-ZS110", "Panasonic DMC-TZ100", "Panasonic DMC-TZ101", "Panasonic DMC-TZ110", "Panasonic DMC-TX1" ], - "global_green_equilibration" : true, "dcraw_matrix": [ 7790,-2736,-755,-3452,11870,1769,-628,1647,4898 ], // dcp_v8.6 d65 "raw_crop": [ 4, 4, -4, -4 ], // full raw frame 5488x3664 Exif crop 5472X3648 with 8pixel borders. Set the borders at 4 pixels which added with RT's 4 pixels border gives exactly the official frame. "ranges": { @@ -1740,14 +1735,12 @@ Camera constants: { // Quality A "make_model": [ "Panasonic DMC-LF1", "Leica C (Typ 112)" ], - "global_green_equilibration" : true, "dcraw_matrix": [ 9379,-3267,-816,-3227,11560,1881,-926,1928,5340 ], "ranges": { "black": 15, "white": 4050 } // 15 is BL offset. dcraw/RT read the base offset from Exif and calculates total BL = BLbase+BLoffset }, { // Quality A "make_model": [ "Panasonic DMC-TZ60", "Panasonic DMC-TZ61", "Panasonic DMC-ZS40", "Panasonic DMC-ZS41" ], - "global_green_equilibration" : true, "dcraw_matrix": [ 8607,-2822,-808,-3755,11930,2049,-820,2060,5224 ], // matrix from Adobe dcp v8.4 "raw_crop": [ 8, 8, -8, -8 ], // crop according to Exif 4896 X 3672 plus 4 pixels borders. RT's frame gets smaller than dcraw but works better with auto distortion "ranges": { "black": 14, "white": 4050 } // 15 is BL offset. dcraw/RT read the base offset from Exif and calculates total BL = BLbase+BLoffset @@ -1755,7 +1748,6 @@ Camera constants: { // Quality B "make_model": [ "Panasonic DMC-TZ70", "Panasonic DMC-TZ71", "Panasonic DMC-ZS50", "Panasonic DMC-ZS51" ], - "global_green_equilibration" : true, "dcraw_matrix": [ 8802,-3135,-789,-3151,11468,1904,-550,1745,4810 ], // DNG_V8.8 D65 "raw_crop": [ 0, 0, -4, -4 ], // full raw 4/3 4144x3016 8,8,3008,4008 = 4000X3000. RT's frame gets smaller than dcraw but works better with auto distortion "ranges": { "black": 14, "white": 4050 } // 12+1+1 is BL offset @@ -1763,7 +1755,6 @@ Camera constants: { // Quality A, samples by Hombre "make_model": [ "Panasonic DC-ZS70", "Panasonic DC-TZ90", "Panasonic DC-TZ91", "Panasonic DC-TZ92", "Panasonic DC-TZ93" ], - "global_green_equilibration" : true, "dcraw_matrix": [ 9052,-3117,-883,-3045,11346,1927,-205,1520,4730 ], // DNG_V9.10.1 D65 "raw_crop": [ 0, 6, -8, -2 ], // fullraw4/3 5264x3904 official 8,8,3896,5192 = 5184X3888. Dcraw 0,0,5200,3904 RT's frame gets smaller than dcraw but works better with auto distortion "ranges": { "black": 16, "white": 4050 } // 12+3+1 is BL offset @@ -1773,7 +1764,6 @@ Camera constants: { // Quality A, Replicated from rawimage.cc "make_model": [ "Panasonic DMC-G10", "Panasonic DMC-G2" ], - "global_green_equilibration" : true, "dcraw_matrix": [ 8310,-1811,-960,-4941,12990,2151,-1378,2468,6860 ], // Colin Walker "ranges": { "black": 15, // 15 is black offset, dcraw/RT read the base black from Exif and calculates total BL = BLbase+BLoffset @@ -1786,7 +1776,6 @@ Camera constants: { // Quality A, Replicated from rawimage.cc "make_model": "Panasonic DMC-G1", - "global_green_equilibration" : true, "dcraw_matrix": [ 7477,-1615,-651,-5016,12769,2506,-1380,2475,7240 ], // Colin Walker "ranges": { "black": 15, // 15 is BL offset. dcraw/RT read the base black from Exif and calculates total BL = BLbase+BLoffset @@ -1799,7 +1788,6 @@ Camera constants: { // Quality A, Replicated from rawimage.cc "make_model": "Panasonic DMC-G3", - "global_green_equilibration" : true, "dcraw_matrix": [ 6051,-1406,-671,-4015,11505,2868,-1654,2667,6219 ], // Colin Walker "ranges": { "black": 15, // 15 is BL offset. dcraw/RT read the base black from Exif and calculates total BL = BLbase+BLoffset @@ -1808,7 +1796,6 @@ Camera constants: { // Quality A, Replicated from rawimage.cc "make_model": "Panasonic DMC-G5", - "global_green_equilibration" : true, "dcraw_matrix": [ 7122,-2092,-419,-4643,11769,3283,-1363,2413,5944 ], // RT "ranges": { "black": 15, // 15 is BL offset. dcraw/RT read the base black from Exif and calculates total BL = BLbase+BLoffset @@ -1817,7 +1804,6 @@ Camera constants: { // Quality A, Replicated from rawimage.cc "make_model": "Panasonic DMC-GF1", - "global_green_equilibration" : true, "dcraw_matrix": [ 7863,-2080,-668,-4623,12331,2578,-1020,2066,7266 ], // Colin Walker "ranges": { "black": 15, // 15 is BL offset. dcraw/RT read the base black from Exif and calculates total BL = BLbase+BLoffset @@ -1830,7 +1816,6 @@ Camera constants: { // Quality A, Replicated from rawimage.cc "make_model": "Panasonic DMC-GF2", - "global_green_equilibration" : true, "dcraw_matrix": [ 7694,-1791,-745,-4917,12818,2332,-1221,2322,7197 ], // Colin Walker "ranges": { "black": 15, // 15 is BL offset. dcraw/RT read the base black from Exif and calculates total BL = BLbase+BLoffset @@ -1839,7 +1824,6 @@ Camera constants: { // Quality A, Replicated from rawimage.cc "make_model": "Panasonic DMC-GF3", - "global_green_equilibration" : true, "dcraw_matrix": [ 8074,-1846,-861,-5026,12999,2239,-1320,2375,7422 ], // Colin Walker "ranges": { "black": 15, // 15 is BL offset. dcraw/RT read the base black from Exif and calculates total BL = BLbase+BLoffset @@ -1848,7 +1832,6 @@ Camera constants: { // Quality A, Replicated from rawimage.cc "make_model": "Panasonic DMC-GH1", - "global_green_equilibration" : true, "dcraw_matrix": [ 6360,-1557,-375,-4201,11504,3086,-1378,2518,5843 ], // Colin Walker "ranges": { "black": 15, // 15 is BL offset. dcraw/RT read the base black from Exif and calculates total BL = BLbase+BLoffset @@ -1861,7 +1844,6 @@ Camera constants: { // Quality A, Replicated from rawimage.cc "make_model": "Panasonic DMC-GH2", - "global_green_equilibration" : true, //"dcraw_matrix": [ 6855,-1765,-456,-4223,11600,2996,-1450,2602,5761 ], // Colin Walker - disabled due to problems with underwater "dcraw_matrix": [ 7780,-2410,-806,-3913,11724,2484,-1018,2390,5298 ], // dcraw d65 "ranges": { @@ -1875,7 +1857,6 @@ Camera constants: { // Quality B, variable WL "make_model": "Panasonic DMC-GH3", - "global_green_equilibration" : true, "dcraw_matrix": [ 6559,-1752,-491,-3672,11407,2586,-962,1875,5130 ], // dcp d65 "ranges": { "black": 16, // 16 is BL offset. dcraw/RT read the base black from Exif and calculates total BL = BLbase+BLoffset @@ -1888,7 +1869,6 @@ Camera constants: { // Quality B, some ISO WLevels are safely guessed "make_model": "Panasonic DMC-GH4", - "global_green_equilibration" : true, "dcraw_matrix": [ 7122,-2108,-512,-3155,11201,2231,-541,1423,5045 ], // dng_v8.5 d65 "ranges": { "black": 16, // 16 is BL offset. dcraw/RT read the base black from Exif and calculates total BL = BLbase+BLoffset @@ -1902,7 +1882,6 @@ Camera constants: { // Quality C "make_model": "Panasonic DC-GH5", - "global_green_equilibration" : true, "dcraw_matrix": [ 7641,-2336,-605,-3218,11299,2187,-485,1338,5121 ], // DNG_v9.9 D65 "ranges": { "black": 15, // 16 is BL offset. dcraw/RT read the base BL from Exif and calculates total BL = BLbase+BLoffset @@ -1916,7 +1895,6 @@ Camera constants: { // Quality A "make_model": "Panasonic DMC-GM1", - "global_green_equilibration" : true, "dcraw_matrix": [ 6770,-1895,-744,-5232,13145,2303,-1664,2691,5703 ], "ranges": { "black": 15, // 15 is BL offset. dcraw/RT read the base black from Exif and calculates total BL = BLbase+BLoffset @@ -1930,7 +1908,6 @@ Camera constants: { // Quality B, uncertainty about ISO100 WL "make_model": "Panasonic DMC-GM5", - "global_green_equilibration" : true, "dcraw_matrix": [ 8238,-3244,-679,-3921,11814,2384,-836,2022,5852 ], // dng_v8.7 d65 "ranges": { "black": 15, // 15 is BL offset. dcraw/RT read the base black from Exif and calculates total BL = BLbase+BLoffset @@ -1943,7 +1920,6 @@ Camera constants: { // Quality A "make_model": [ "Panasonic DMC-GX7", "Panasonic DMC-GF7", "Panasonic DMC-GF8" ], - "global_green_equilibration" : true, "dcraw_matrix": [ 7610,-2780,-576,-4614,12195,2733,-1375,2393,6490 ], "ranges": { "black": 15, // 15 is BL offset. dcraw/RT read the base black from Exif and calculates total BL = BLbase+BLoffset @@ -1957,7 +1933,6 @@ Camera constants: { // Quality A "make_model": [ "Panasonic DMC-G7", "Panasonic DMC-G70" ], - "global_green_equilibration" : true, "dcraw_matrix": [ 7610,-2780,-576,-4614,12195,2733,-1375,2393,6490 ], // DNG_v9.1 D65 "ranges": { "black": 16, // 16 is BL offset. dcraw/RT read the base black from Exif and calculates total BL = BLbase+BLoffset @@ -1971,7 +1946,6 @@ Camera constants: { // Quality B "make_model": [ "Panasonic DMC-GX80", "Panasonic DMC-GX85", "Panasonic DMC-GX7MK2" ], - "global_green_equilibration" : true, "dcraw_matrix": [ 7771,-3020,-629,-4029,11950,2345,-821,1977,6119 ], // DNG_v9.6 D65 "ranges": { "black": 16, // 16 is BL offset. dcraw/RT read the base black from Exif and calculates total BL = BLbase+BLoffset @@ -1985,7 +1959,6 @@ Camera constants: { // Quality X, no white-frames nor black-frames yet, see #4550 "make_model": [ "Panasonic DC-GX9" ], - "global_green_equilibration" : true, "dcraw_matrix": [ 7564,-2263,-606,-3148,11239,2177,-540,1435,4853 ], // ColorMatrix2 from Adobe DNG Converter 10.3 "ranges": { "black": 16, @@ -1995,7 +1968,6 @@ Camera constants: { // Quality B, Same as Panasonic G7 "make_model": [ "Panasonic DMC-G8", "Panasonic DMC-G80", "Panasonic DMC-G81", "Panasonic DMC-G85" ], - "global_green_equilibration" : true, "dcraw_matrix": [ 7610,-2780,-576,-4614,12195,2733,-1375,2393,6490 ], // DNG_v9.7 D65 "ranges": { "black": 16, // 16 is BL offset. dcraw/RT read the base black from Exif and calculates total BL = BLbase+BLoffset @@ -2009,7 +1981,6 @@ Camera constants: { // Quality B "make_model": "Panasonic DMC-GX8", - "global_green_equilibration" : true, "dcraw_matrix": [ 7564,-2263,-606,-3148,11239,2177,-540,1435,4853 ], // DNG_v9.1.1 D65 "ranges": { "black": 15, // 16 is BL offset. dcraw/RT read the base BL from Exif and calculates total BL = BLbase+BLoffset @@ -2023,7 +1994,6 @@ Camera constants: { // Quality B, samples by Ingo, missing some long exposure at high ISO samples with LENR ON "make_model": [ "Panasonic DMC-LX100", "Leica D-LUX (Typ 109)" ], - "global_green_equilibration" : true, "dcraw_matrix": [ 8844,-3538,-768,-3709,11762,2200,-698,1792,5220 ], // DNG_V8.7 d65 //"dcraw_matrix": [ 6538,-1614,-549,-5475,13096,2646,-1780,2799,5612 ], // calculated from DxO D50 "ranges": { @@ -2044,7 +2014,6 @@ Camera constants: { // Quality B, Intermediate ISOs missing "make_model": [ "Panasonic DMC-LX9", "Panasonic DMC-LX10", "Panasonic DMC-LX15" ], - "global_green_equilibration" : true, "dcraw_matrix": [ 7790,-2736,-755,-3452,11870,1769,-628,1647,4898 ], // DNg_v9.8 d65 "raw_crop": [ 4, 4, -4, -4 ], // full raw frame 5488x3664 Exif crop 5472X3648 with 8pixel borders. Set the borders at 4 pixels which added with RT's 4 pixels border gives exactly the official frame. "ranges": { From a3055f355282232743bbf8df07e00921214407c8 Mon Sep 17 00:00:00 2001 From: heckflosse Date: Tue, 12 Jun 2018 17:59:10 +0200 Subject: [PATCH 34/42] Small speedup for rl sharpening when damping = 0, no issue --- rtengine/gauss.cc | 40 ++++++++++++++++++++-------------------- rtengine/ipsharpen.cc | 10 ---------- 2 files changed, 20 insertions(+), 30 deletions(-) diff --git a/rtengine/gauss.cc b/rtengine/gauss.cc index 3b03afdee..2468e52d2 100644 --- a/rtengine/gauss.cc +++ b/rtengine/gauss.cc @@ -163,15 +163,15 @@ template void gauss3x3div (T** RESTRICT src, T** RESTRICT dst, T** REST #pragma omp single nowait #endif { - dst[0][0] = divBuffer[0][0] / (src[0][0] > 0.f ? src[0][0] : 1.f); + dst[0][0] = rtengine::max(divBuffer[0][0] / (src[0][0] > 0.f ? src[0][0] : 1.f), 0.f); for (int j = 1; j < W - 1; j++) { float tmp = (b1 * (src[0][j - 1] + src[0][j + 1]) + b0 * src[0][j]); - dst[0][j] = divBuffer[0][j] / (tmp > 0.f ? tmp : 1.f); + dst[0][j] = rtengine::max(divBuffer[0][j] / (tmp > 0.f ? tmp : 1.f), 0.f); } - dst[0][W - 1] = divBuffer[0][W - 1] / (src[0][W - 1] > 0.f ? src[0][W - 1] : 1.f); + dst[0][W - 1] = rtengine::max(divBuffer[0][W - 1] / (src[0][W - 1] > 0.f ? src[0][W - 1] : 1.f), 0.f); } #ifdef _OPENMP @@ -180,15 +180,15 @@ template void gauss3x3div (T** RESTRICT src, T** RESTRICT dst, T** REST for (int i = 1; i < H - 1; i++) { float tmp = (b1 * (src[i - 1][0] + src[i + 1][0]) + b0 * src[i][0]); - dst[i][0] = divBuffer[i][0] / (tmp > 0.f ? tmp : 1.f); + dst[i][0] = rtengine::max(divBuffer[i][0] / (tmp > 0.f ? tmp : 1.f), 0.f); for (int j = 1; j < W - 1; j++) { tmp = (c2 * (src[i - 1][j - 1] + src[i - 1][j + 1] + src[i + 1][j - 1] + src[i + 1][j + 1]) + c1 * (src[i - 1][j] + src[i][j - 1] + src[i][j + 1] + src[i + 1][j]) + c0 * src[i][j]); - dst[i][j] = divBuffer[i][j] / (tmp > 0.f ? tmp : 1.f); + dst[i][j] = rtengine::max(divBuffer[i][j] / (tmp > 0.f ? tmp : 1.f), 0.f); } tmp = (b1 * (src[i - 1][W - 1] + src[i + 1][W - 1]) + b0 * src[i][W - 1]); - dst[i][W - 1] = divBuffer[i][W - 1] / (tmp > 0.f ? tmp : 1.f); + dst[i][W - 1] = rtengine::max(divBuffer[i][W - 1] / (tmp > 0.f ? tmp : 1.f), 0.f); } // last row @@ -196,14 +196,14 @@ template void gauss3x3div (T** RESTRICT src, T** RESTRICT dst, T** REST #pragma omp single #endif { - dst[H - 1][0] = divBuffer[H - 1][0] / (src[H - 1][0] > 0.f ? src[H - 1][0] : 1.f); + dst[H - 1][0] = rtengine::max(divBuffer[H - 1][0] / (src[H - 1][0] > 0.f ? src[H - 1][0] : 1.f), 0.f); for (int j = 1; j < W - 1; j++) { float tmp = (b1 * (src[H - 1][j - 1] + src[H - 1][j + 1]) + b0 * src[H - 1][j]); - dst[H - 1][j] = divBuffer[H - 1][j] / (tmp > 0.f ? tmp : 1.f); + dst[H - 1][j] = rtengine::max(divBuffer[H - 1][j] / (tmp > 0.f ? tmp : 1.f), 0.f); } - dst[H - 1][W - 1] = divBuffer[H - 1][W - 1] / (src[H - 1][W - 1] > 0.f ? src[H - 1][W - 1] : 1.f); + dst[H - 1][W - 1] = rtengine::max(divBuffer[H - 1][W - 1] / (src[H - 1][W - 1] > 0.f ? src[H - 1][W - 1] : 1.f), 0.f); } } @@ -859,8 +859,8 @@ template void gaussVerticalSsediv (T** src, T** dst, T** divBuffer, con Tv1 = Rv1; Rv = LVF(tmp[j][0]) * Bv + Tv * b1v + Tm2v * b2v + Tm3v * b3v; Rv1 = LVF(tmp[j][4]) * Bv + Tv1 * b1v + Tm2v1 * b2v + Tm3v1 * b3v; - STVFU( dst[j][i], LVFU(divBuffer[j][i]) / vself(vmaskf_gt(Rv, ZEROV), Rv, onev)); - STVFU( dst[j][i + 4], LVFU(divBuffer[j][i + 4]) / vself(vmaskf_gt(Rv1, ZEROV), Rv1, onev)); + STVFU( dst[j][i], vmaxf(LVFU(divBuffer[j][i]) / vself(vmaskf_gt(Rv, ZEROV), Rv, onev), ZEROV)); + STVFU( dst[j][i + 4], vmaxf(LVFU(divBuffer[j][i + 4]) / vself(vmaskf_gt(Rv1, ZEROV), Rv1, onev), ZEROV)); Tm3v = Tm2v; Tm3v1 = Tm2v1; Tm2v = Tv; @@ -895,7 +895,7 @@ template void gaussVerticalSsediv (T** src, T** dst, T** divBuffer, con } for (int j = 0; j < H; j++) { - dst[j][i] = divBuffer[j][i] / (tmp[j][0] > 0.f ? tmp[j][0] : 1.f); + dst[j][i] = rtengine::max(divBuffer[j][i] / (tmp[j][0] > 0.f ? tmp[j][0] : 1.f), 0.f); } } @@ -1020,14 +1020,14 @@ template void gaussVerticaldiv (T** src, T** dst, T** divBuffer, const } for (int k = 0; k < numcols; k++) { - dst[H - 1][i + k] = divBuffer[H - 1][i + k] / (temp2[H - 1][k] = temp2Hm1[k]); - dst[H - 2][i + k] = divBuffer[H - 2][i + k] / (temp2[H - 2][k] = B * temp2[H - 2][k] + b1 * temp2[H - 1][k] + b2 * temp2H[k] + b3 * temp2Hp1[k]); - dst[H - 3][i + k] = divBuffer[H - 3][i + k] / (temp2[H - 3][k] = B * temp2[H - 3][k] + b1 * temp2[H - 2][k] + b2 * temp2[H - 1][k] + b3 * temp2H[k]); + rtengine::max(dst[H - 1][i + k] = divBuffer[H - 1][i + k] / (temp2[H - 1][k] = temp2Hm1[k]), 0.f); + rtengine::max(dst[H - 2][i + k] = divBuffer[H - 2][i + k] / (temp2[H - 2][k] = B * temp2[H - 2][k] + b1 * temp2[H - 1][k] + b2 * temp2H[k] + b3 * temp2Hp1[k]), 0.f); + rtengine::max(dst[H - 3][i + k] = divBuffer[H - 3][i + k] / (temp2[H - 3][k] = B * temp2[H - 3][k] + b1 * temp2[H - 2][k] + b2 * temp2[H - 1][k] + b3 * temp2H[k], 0.f); } for (int j = H - 4; j >= 0; j--) { for (int k = 0; k < numcols; k++) { - dst[j][i + k] = divBuffer[j][i + k] / (temp2[j][k] = B * temp2[j][k] + b1 * temp2[j + 1][k] + b2 * temp2[j + 2][k] + b3 * temp2[j + 3][k]); + rtengine::max(dst[j][i + k] = divBuffer[j][i + k] / (temp2[j][k] = B * temp2[j][k] + b1 * temp2[j + 1][k] + b2 * temp2[j + 2][k] + b3 * temp2[j + 3][k]), 0.f); } } } @@ -1050,12 +1050,12 @@ template void gaussVerticaldiv (T** src, T** dst, T** divBuffer, const double temp2H = src[H - 1][i] + M[1][0] * (temp2[H - 1][0] - src[H - 1][i]) + M[1][1] * (temp2[H - 2][0] - src[H - 1][i]) + M[1][2] * (temp2[H - 3][0] - src[H - 1][i]); double temp2Hp1 = src[H - 1][i] + M[2][0] * (temp2[H - 1][0] - src[H - 1][i]) + M[2][1] * (temp2[H - 2][0] - src[H - 1][i]) + M[2][2] * (temp2[H - 3][0] - src[H - 1][i]); - dst[H - 1][i] = divBuffer[H - 1][i] / (temp2[H - 1][0] = temp2Hm1); - dst[H - 2][i] = divBuffer[H - 2][i] / (temp2[H - 2][0] = B * temp2[H - 2][0] + b1 * temp2[H - 1][0] + b2 * temp2H + b3 * temp2Hp1); - dst[H - 3][i] = divBuffer[H - 3][i] / (temp2[H - 3][0] = B * temp2[H - 3][0] + b1 * temp2[H - 2][0] + b2 * temp2[H - 1][0] + b3 * temp2H); + rtengine::max(dst[H - 1][i] = divBuffer[H - 1][i] / (temp2[H - 1][0] = temp2Hm1), 0.f); + rtengine::max(dst[H - 2][i] = divBuffer[H - 2][i] / (temp2[H - 2][0] = B * temp2[H - 2][0] + b1 * temp2[H - 1][0] + b2 * temp2H + b3 * temp2Hp1), 0.f); + rtengine::max(dst[H - 3][i] = divBuffer[H - 3][i] / (temp2[H - 3][0] = B * temp2[H - 3][0] + b1 * temp2[H - 2][0] + b2 * temp2[H - 1][0] + b3 * temp2H), 0.f); for (int j = H - 4; j >= 0; j--) { - dst[j][i] = divBuffer[j][i] / (temp2[j][0] = B * temp2[j][0] + b1 * temp2[j + 1][0] + b2 * temp2[j + 2][0] + b3 * temp2[j + 3][0]); + rtengine::max(dst[j][i] = divBuffer[j][i] / (temp2[j][0] = B * temp2[j][0] + b1 * temp2[j + 1][0] + b2 * temp2[j + 2][0] + b3 * temp2[j + 3][0]), 0.f); } } } diff --git a/rtengine/ipsharpen.cc b/rtengine/ipsharpen.cc index 855a8a8c9..0b561ae9a 100644 --- a/rtengine/ipsharpen.cc +++ b/rtengine/ipsharpen.cc @@ -190,22 +190,12 @@ BENCHFUN if (!needdamp) { // apply gaussian blur and divide luminance by result of gaussian blur gaussianBlur(tmpI, tmp, W, H, sigma, nullptr, GAUSS_DIV, luminance); -#ifdef _OPENMP - #pragma omp for -#endif - for (int i = 0; i < H; ++i) { - for(int j = 0; j < W; ++j) { - tmp[i][j] = max(tmp[i][j], 0.f); - } - } } else { // apply gaussian blur + damping gaussianBlur(tmpI, tmp, W, H, sigma); dcdamping(tmp, luminance, damping, W, H); } - gaussianBlur(tmp, tmpI, W, H, sigma, nullptr, GAUSS_MULT); - } // end for #ifdef _OPENMP From 1425977f35179114542ba388d5bb28018f909650 Mon Sep 17 00:00:00 2001 From: Morgan Hardwood Date: Wed, 13 Jun 2018 10:41:59 +0200 Subject: [PATCH 35/42] Japanese translation updated by firefly, closes #4604 --- rtdata/languages/Japanese | 74 +++++++++++++++++++++------------------ 1 file changed, 40 insertions(+), 34 deletions(-) diff --git a/rtdata/languages/Japanese b/rtdata/languages/Japanese index 41672fd6c..540b59521 100644 --- a/rtdata/languages/Japanese +++ b/rtdata/languages/Japanese @@ -164,7 +164,7 @@ FILEBROWSER_MOVETODARKFDIR;ダークフレーム・ディレクトリに移動 FILEBROWSER_MOVETOFLATFIELDDIR;フラットフィールド・ディレクトリに移動 FILEBROWSER_NEW_NAME;新しい名前: FILEBROWSER_OPENDEFAULTVIEWER;Windowsのデフォルト・ビューア(キュー処理) -FILEBROWSER_PARTIALPASTEPROFILE;プロファイルの貼り付け - 一部 +FILEBROWSER_PARTIALPASTEPROFILE;プロファイルの貼り付け - 一部 FILEBROWSER_PASTEPROFILE;プロファイルの貼り付け FILEBROWSER_POPUPCANCELJOB;ジョブ キャンセル FILEBROWSER_POPUPCOLORLABEL;カラー・ラベル @@ -186,11 +186,11 @@ FILEBROWSER_POPUPPROCESSFAST;キューに追加 (高速書き出し) FILEBROWSER_POPUPPROFILEOPERATIONS;プロファイルの操作 FILEBROWSER_POPUPRANK;ランク FILEBROWSER_POPUPRANK0;ランクなし -FILEBROWSER_POPUPRANK1;ランク 1 * +FILEBROWSER_POPUPRANK1;ランク 1 * FILEBROWSER_POPUPRANK2;ランク 2 ** -FILEBROWSER_POPUPRANK3;ランク 3 *** -FILEBROWSER_POPUPRANK4;ランク 4 **** -FILEBROWSER_POPUPRANK5;ランク 5 ***** +FILEBROWSER_POPUPRANK3;ランク 3 *** +FILEBROWSER_POPUPRANK4;ランク 4 **** +FILEBROWSER_POPUPRANK5;ランク 5 ***** FILEBROWSER_POPUPREMOVE;ファイルシステムから削除 FILEBROWSER_POPUPREMOVEINCLPROC;ファイルシステムとバッチの結果から削除 FILEBROWSER_POPUPRENAME;名前変更 @@ -530,15 +530,15 @@ HISTORY_MSG_248;L*a*b* HH カーブ HISTORY_MSG_249;ディテールレベルのコントラスト - しきい値 HISTORY_MSG_250;ノイズ低減 - 強化 HISTORY_MSG_251;白黒 - アルゴリズム -HISTORY_MSG_252;CbDL 肌色の目標/保護 -HISTORY_MSG_253;CbDL アーティファクトを軽減 -HISTORY_MSG_254;CbDL 肌色の色相 -HISTORY_MSG_255;ノイズ低減 - メディアン +HISTORY_MSG_252;CbDL 肌色の目標/保護 +HISTORY_MSG_253;CbDL アーティファクトを軽減 +HISTORY_MSG_254;CbDL 肌色の色相 +HISTORY_MSG_255;ノイズ低減 - メディアン HISTORY_MSG_256;ノイズ低減 - フィルターの種類 HISTORY_MSG_257;カラートーン調整 HISTORY_MSG_258;カラートーン調整 - カラーのカーブ HISTORY_MSG_259;カラートーン調整 - 不透明度のカーブ -HISTORY_MSG_260;カラートーン調整 - a*(b*)の不透明度 +HISTORY_MSG_260;カラートーン調整 - a*(b*)の不透明度 HISTORY_MSG_261;カラートーン調整 - 方法 HISTORY_MSG_262;カラートーン調整 - b*の不透明度 HISTORY_MSG_263;カラートーン調整 - シャドウのレッド @@ -550,7 +550,7 @@ HISTORY_MSG_268;カラートーン調整 - 中間トーンのブルー HISTORY_MSG_269;カラートーン調整 - ハイライトのレッド HISTORY_MSG_270;カラートーン調整 - ハイライトのグリーン HISTORY_MSG_271;カラートーン調整 - ハイライトのブルー -HISTORY_MSG_272;カラートーン調整 - バランス +HISTORY_MSG_272;カラートーン調整 - バランス HISTORY_MSG_273;カラートーン調整 - SMHでカラーバランス HISTORY_MSG_274;カラートーン調整 - シャドウの彩度 HISTORY_MSG_275;カラートーン調整 - ハイライトの彩度 @@ -558,7 +558,7 @@ HISTORY_MSG_276;カラートーン調整 - 不透明度 HISTORY_MSG_277;カラートーン調整 - カーブをリセット HISTORY_MSG_278;カラートーン調整 - 明度を維持 HISTORY_MSG_279;カラートーン調整 - シャドウ -HISTORY_MSG_280;カラートーン調整 - ハイライト +HISTORY_MSG_280;カラートーン調整 - ハイライト HISTORY_MSG_281;カラートーン調整 - 彩度の保護 HISTORY_MSG_282;カラートーン調整 - 彩度のしきい値 HISTORY_MSG_283;カラートーン調整 - 強さを維持 @@ -583,7 +583,7 @@ HISTORY_MSG_301;輝度ノイズの調整方法 HISTORY_MSG_302;色ノイズの調整方法 HISTORY_MSG_303;色ノイズの調整方法 HISTORY_MSG_304;W- コントラストレベル -HISTORY_MSG_305;ウェーブレットのレベル +HISTORY_MSG_305;ウェーブレット HISTORY_MSG_306;W- プロセス HISTORY_MSG_307;W- プレビュー HISTORY_MSG_308;W- プレビューの方向 @@ -623,8 +623,8 @@ HISTORY_MSG_341;W- エッジパフォーマンス HISTORY_MSG_342;W- ES 最初のレベル HISTORY_MSG_343;W- 色度のレベル HISTORY_MSG_344;W- 色度 方式 スライダー/カーブ -HISTORY_MSG_345;W- ES ローカルコントラスト -HISTORY_MSG_346;W- ES ローカルコントラスト 方式 +HISTORY_MSG_345;W- ES ローカルコントラスト +HISTORY_MSG_346;W- ES ローカルコントラスト 方式 HISTORY_MSG_347;W- ノイズ低減とリファイン レベル1 HISTORY_MSG_348;W- ノイズ低減とリファイン レベル2 HISTORY_MSG_349;W- ノイズ低減とリファイン レベル3 @@ -750,6 +750,9 @@ HISTORY_MSG_484;CAM02 - 撮影環境のYb 自動 HISTORY_MSG_485;レンズ補正 HISTORY_MSG_486;レンズ補正 - カメラ HISTORY_MSG_487;レンズ補正 - レンズ +HISTORY_MSG_488;ダイナミックレンジ圧縮 +HISTORY_MSG_489;DRC - しきい値 +HISTORY_MSG_490;DRC - 量 HISTORY_MSG_491;ホワイトバランス HISTORY_MSG_492;RGBカーブ HISTORY_MSG_493;L*a*b*調整 @@ -767,6 +770,7 @@ HISTORY_MSG_PREPROCESS_LINEDENOISE_DIRECTION;ラインノイズフィルタの HISTORY_MSG_PREPROCESS_PDAFLINESFILTER;PDAFラインフィルタ HISTORY_MSG_PRSHARPEN_CONTRAST;PRS - コントラストのしきい値 HISTORY_MSG_SHARPENING_CONTRAST;シャープ化 - コントラストのしきい値 +HISTORY_MSG_TM_FATTAL_ANCHOR;DRC - アンカー HISTORY_NEWSNAPSHOT;追加 HISTORY_NEWSNAPSHOT_TOOLTIP;ショートカット: Alt-s HISTORY_SNAPSHOT;スナップショット @@ -979,6 +983,7 @@ PARTIALPASTE_SHADOWSHIGHLIGHTS;シャドウ/ハイライト PARTIALPASTE_SHARPENEDGE;エッジ PARTIALPASTE_SHARPENING;シャープ化 (USM/RL) PARTIALPASTE_SHARPENMICRO;マイクロコントラスト +PARTIALPASTE_TM_FATTAL;ダイナミックレンジ圧縮 PARTIALPASTE_VIBRANCE;自然な彩度 PARTIALPASTE_VIGNETTING;周辺光量補正 PARTIALPASTE_WAVELETGROUP;ウェーブレット処理 @@ -1522,10 +1527,10 @@ TP_DIRPYRDENOISE_CHROMINANCE_METHODADVANCED_TOOLTIP;手動\n画像全体に作 TP_DIRPYRDENOISE_CHROMINANCE_METHOD_TOOLTIP;手動\n画像全体に作用します\nノイズ低減の設定を手動で行います\n\n自動(分割方式)\n画像全体に作用します\n画像を9つに分割して、そこから全体の色ノイズ低減に適した設定を自動的に行います\n\n自動(多分割方式)\nプレビュー画像には反映されません-保存画像だけに反映されます。但し、タイルサイズとその中心をプレビューサイズとその中心にマッチさせる〝プレビュー”方式を使えば、効果がどれ位か予測がつきます。\n画像をタイル状に分割し(タイル数は画像サイズ次第で、10~70枚になります)、各タイルにあった色ノイズ低減の設定を自動で行います\n\n自動(プレビュー方式)\n画像全体に作用します\nプレビューで見えている画像の一部を使って全体の色ノイズ低減に適した設定を自動で行います TP_DIRPYRDENOISE_CHROMINANCE_PMZ;自動(プレビュー方式) TP_DIRPYRDENOISE_CHROMINANCE_PREVIEW;プレビュー方式 -TP_DIRPYRDENOISE_CHROMINANCE_PREVIEWRESIDUAL_INFO_TOOLTIP;ウェーブレット変換後、プレビューで見える部分画像で残ったノイズのレベルを表示します\n\n>300以上 非常にノイズが多い\n100~300 ノイズが多い\n50~100 ノイズが少ない\n50以下 ノイズが非常に少ない\n\n算出値はRGBとL*a*b*モードでは異なります。RGBモードは輝度と色を完全に切り離すことが出来ないので、算出値の精度は劣ります。 -TP_DIRPYRDENOISE_CHROMINANCE_PREVIEW_INFO;プレビューのサイズ=%1, 中心: Px=%2 Py=%3 -TP_DIRPYRDENOISE_CHROMINANCE_PREVIEW_NOISEINFO;プレビューのノイズ: 中間色度=%1 高色度=%2 -TP_DIRPYRDENOISE_CHROMINANCE_PREVIEW_NOISEINFO_EMPTY;プレビューのノイズ: 中間色度= - 高色度= - +TP_DIRPYRDENOISE_CHROMINANCE_PREVIEWRESIDUAL_INFO_TOOLTIP;ウェーブレット変換後、プレビューに表示されている画像のノイズのレベルを表示します\n\n>300以上 非常にノイズが多い\n100~300 ノイズが多い\n50~100 ノイズが少ない\n50以下 ノイズが非常に少ない\n\n算出値はRGBとL*a*b*モードでは異なります。RGBモードは輝度と色を完全に切り離すことが出来ないので、算出値の精度は劣ります。 +TP_DIRPYRDENOISE_CHROMINANCE_PREVIEW_INFO;プレビュー画像のサイズ=%1, 中心: Px=%2 Py=%3 +TP_DIRPYRDENOISE_CHROMINANCE_PREVIEW_NOISEINFO;プレビュー画像のノイズ: 平均値=%1 最大値=%2 +TP_DIRPYRDENOISE_CHROMINANCE_PREVIEW_NOISEINFO_EMPTY;プレビュー画像のノイズ: 平均値= - 最大値= - TP_DIRPYRDENOISE_CHROMINANCE_PREVIEW_TILEINFO;タイルのサイズ=%1, 中心位置: X座標=%2 Y座標=%3 TP_DIRPYRDENOISE_CHROMINANCE_REDGREEN;色差 レッド/グリーン TP_DIRPYRDENOISE_ENH;強化モード @@ -1536,17 +1541,17 @@ TP_DIRPYRDENOISE_LUMINANCE_CURVE;輝度カーブ TP_DIRPYRDENOISE_LUMINANCE_DETAIL;輝度 細部の復元 TP_DIRPYRDENOISE_LUMINANCE_FRAME;輝度ノイズ TP_DIRPYRDENOISE_LUMINANCE_SMOOTHING;輝度 -TP_DIRPYRDENOISE_MAIN_COLORSPACE;方式 +TP_DIRPYRDENOISE_MAIN_COLORSPACE;色空間 TP_DIRPYRDENOISE_MAIN_COLORSPACE_LAB;L*a*b* TP_DIRPYRDENOISE_MAIN_COLORSPACE_LABEL;ノイズ低減 TP_DIRPYRDENOISE_MAIN_COLORSPACE_RGB;RGB TP_DIRPYRDENOISE_MAIN_COLORSPACE_TOOLTIP;raw画像は、RGBまたはL*a*b*方式のいずれかを使用することができます。\n\nraw以外の画像は、選択にかかわらずL*a*b*方式が採用されます TP_DIRPYRDENOISE_MAIN_GAMMA;ガンマ TP_DIRPYRDENOISE_MAIN_GAMMA_TOOLTIP;ガンマは、トーンの範囲全体でノイズ低減の量を変化させます。値が大きいほど明るいトーンに効果を及ぼし、値が小さいほどシャドウをターゲットにします -TP_DIRPYRDENOISE_MAIN_MODE;ノイズ低減の質 -TP_DIRPYRDENOISE_MAIN_MODE_AGGRESSIVE;高い -TP_DIRPYRDENOISE_MAIN_MODE_CONSERVATIVE;標準 -TP_DIRPYRDENOISE_MAIN_MODE_TOOLTIP;ノイズの状態に応じて低減効果の質を選べます:1-標準 2-高い\n2の方がノイズ低減効果は高くなりますが、その分処理時間が増えます。 +TP_DIRPYRDENOISE_MAIN_MODE;モード +TP_DIRPYRDENOISE_MAIN_MODE_AGGRESSIVE;積極的 +TP_DIRPYRDENOISE_MAIN_MODE_CONSERVATIVE;控えめ +TP_DIRPYRDENOISE_MAIN_MODE_TOOLTIP;”控えめ”モードは低周波の色度パターンが維持されますが、”積極的”モードではそれらも取り除かれます TP_DIRPYRDENOISE_MEDIAN_METHOD;方式 TP_DIRPYRDENOISE_MEDIAN_METHOD_CHROMINANCE;色ノイズだけ TP_DIRPYRDENOISE_MEDIAN_METHOD_LAB;L*a*b* @@ -1619,7 +1624,7 @@ TP_EXPOSURE_TCMODE_SATANDVALBLENDING;彩度と明度のブレンド TP_EXPOSURE_TCMODE_STANDARD;標準 TP_EXPOSURE_TCMODE_WEIGHTEDSTD;加重平均 TP_EXPOS_BLACKPOINT_LABEL;raw ブラック・ポイント -TP_EXPOS_WHITEPOINT_LABEL;raw ホワイト・ポイント +TP_EXPOS_WHITEPOINT_LABEL;raw ホワイト・ポイント TP_FILMSIMULATION_LABEL;フィルムシミュレーション TP_FILMSIMULATION_SLOWPARSEDIR;RawTherapeeはフィルムシミュレーション機能に使う画像をHald CLUTフォルダーの中から探すよう設計されています(プログラムに組み込むにはフォルダーが大き過ぎるため)。\n変更するには、環境設定 > 画像処理 > フィルムシミュレーションと進み\nどのフォルダーが使われているか確認します。機能を利用する場合は、Hald CLUTだけが入っているフォルダーを指定するか、 この機能を使わない場合はそのフォルダーを空にしておきます。\n\n詳しくはRawPediaを参照して下さい。\n\nフィルム画像のスキャンを止めますか? TP_FILMSIMULATION_STRENGTH;強さ @@ -1998,6 +2003,10 @@ TP_SHARPENMICRO_CONTRAST;コントラストのしきい値 TP_SHARPENMICRO_LABEL;マイクロコントラスト TP_SHARPENMICRO_MATRIX;3×3マトリクスの代わりに 5×5 TP_SHARPENMICRO_UNIFORMITY;均等 +TP_TM_FATTAL_AMOUNT;量 +TP_TM_FATTAL_ANCHOR;アンカー +TP_TM_FATTAL_LABEL;ダイナミックレンジ圧縮 +TP_TM_FATTAL_THRESHOLD;しきい値 TP_VIBRANCE_AVOIDCOLORSHIFT;色ずれを回避 TP_VIBRANCE_CURVEEDITOR_SKINTONES;HH TP_VIBRANCE_CURVEEDITOR_SKINTONES_LABEL;肌色トーン @@ -2245,12 +2254,9 @@ ZOOMPANEL_ZOOMOUT;ズームアウト\nショートカット: - ! Untranslated keys follow; remove the ! prefix after an entry is translated. !!!!!!!!!!!!!!!!!!!!!!!!! -!HISTORY_MSG_488;Dynamic Range Compression -!HISTORY_MSG_489;DRC - Threshold -!HISTORY_MSG_490;DRC - Amount -!HISTORY_MSG_TM_FATTAL_ANCHOR;DRC - Anchor -!PARTIALPASTE_TM_FATTAL;Dynamic Range Compression -!TP_TM_FATTAL_AMOUNT;Amount -!TP_TM_FATTAL_ANCHOR;Anchor -!TP_TM_FATTAL_LABEL;Dynamic Range Compression -!TP_TM_FATTAL_THRESHOLD;Threshold +!HISTORY_MSG_DUALDEMOSAIC_CONTRAST;AMaZE+VNG4 - Contrast threshold +!HISTORY_MSG_PIXELSHIFT_DEMOSAIC;PS - Demosaic method for motion +!TP_RAW_4PASS;4-Pass +!TP_RAW_AMAZEVNG4;AMaZE+VNG4 +!TP_RAW_DUALDEMOSAICCONTRAST;Contrast threshold +!TP_RAW_PIXELSHIFTDMETHOD;Demosaic method for motion From 573e39719ea3ff732e83d64e4618432b1add86e9 Mon Sep 17 00:00:00 2001 From: Morgan Hardwood Date: Wed, 13 Jun 2018 10:42:24 +0200 Subject: [PATCH 36/42] French translation updated by lebarhon, closes #4603 --- rtdata/languages/Francais | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/rtdata/languages/Francais b/rtdata/languages/Francais index 4e5435f71..8ab919cc2 100644 --- a/rtdata/languages/Francais +++ b/rtdata/languages/Francais @@ -1464,7 +1464,7 @@ TP_DIRPYRDENOISE_CHROMINANCE_METHODADVANCED_TOOLTIP;Manuel\nAgit sur l'image ent TP_DIRPYRDENOISE_CHROMINANCE_METHOD_TOOLTIP;Manuel\nAgit sur l'image entière.\nVous controlez les paramètres de réduction de bruit manuellement.\n\nGlobal automatique\nAgit sur l'image entière.\n9 zones sont utilisées pour calculer un réglage de réduction de bruit de chroma.\n\nAutomatique multi-zones\nPas d'aperçu - ne fonctionne que lors de l'enregistrement, mais utiliser la méthode "Aperçu" en faisant correspondre la taille et le centre de la tuile à la taille et au centre de l'aperçu, vous permet d'avoir une idée des résultats attendus.\nL'image est divisé en tuiles (entre 10 et 70 en fonction de la taille de l'image) et chaque tuile reçoit son propre réglage de réduction de bruit de chrominance.\n\nAperçu\nAgit sur l'image entière.\nLa partie de l'image visible dans l'aperçu est utilisé pour calculer un réglage de réduction de bruit de chroma. TP_DIRPYRDENOISE_CHROMINANCE_PMZ;Aperçu multi-zones TP_DIRPYRDENOISE_CHROMINANCE_PREVIEW;Aperçu -TP_DIRPYRDENOISE_CHROMINANCE_PREVIEWRESIDUAL_INFO_TOOLTIP;Affiche les niveaux de bruit résiduel de la partie de l'image visible dans l'aperçu après les ondelettes.\n\n>300 Très bruité\n100-300 Bruité\n50-100 Peu bruité\n<50 Très peu bruité\n\nAttention, les valeurs diffèreront entre le mode RVB et L*a*b*. Les valeurs RVB sont moins précises car le mode RVB ne séparent pas complètement la luminance et la chrominance. +TP_DIRPYRDENOISE_CHROMINANCE_PREVIEWRESIDUAL_INFO_TOOLTIP;Affiche les niveaux de bruit résiduels de la partie de l'image visible dans l'aperçu après les ondelettes.\n\n>300 Très bruité\n100-300 Bruité\n50-100 Peu bruité\n<50 Très peu bruité\n\nAttention, les valeurs diffèreront entre le mode RVB et L*a*b*. Les valeurs RVB sont moins précises car le mode RVB ne séparent pas complètement la luminance et la chrominance. TP_DIRPYRDENOISE_CHROMINANCE_PREVIEW_INFO;Taille de l'aperçu=%1, Centre: Px=%2 Py=%3 TP_DIRPYRDENOISE_CHROMINANCE_PREVIEW_NOISEINFO;Bruit de l'aperçu: Moyen=%1 Haut=%2 TP_DIRPYRDENOISE_CHROMINANCE_PREVIEW_NOISEINFO_EMPTY;Bruit de l'aperçu: Moyen= - Haut= - @@ -1478,18 +1478,18 @@ TP_DIRPYRDENOISE_LUMINANCE_CURVE;Courbe de luminance TP_DIRPYRDENOISE_LUMINANCE_DETAIL;Niveau de détails de Luminance TP_DIRPYRDENOISE_LUMINANCE_FRAME;Luminance TP_DIRPYRDENOISE_LUMINANCE_SMOOTHING;Luminance -TP_DIRPYRDENOISE_MAIN_COLORSPACE;Méthode +TP_DIRPYRDENOISE_MAIN_COLORSPACE;Espace colorimétrique TP_DIRPYRDENOISE_MAIN_COLORSPACE_LAB;Lab TP_DIRPYRDENOISE_MAIN_COLORSPACE_LABEL;Réduction du bruit TP_DIRPYRDENOISE_MAIN_COLORSPACE_RGB;RVB TP_DIRPYRDENOISE_MAIN_COLORSPACE_TOOLTIP;Pour les images raw, les méthodes RVB ou Lab peuvent être utilisées.\n\nPour les images non-raw la méthode Lab sera utilisée, indépendamment de ce qu'indique ce bouton. TP_DIRPYRDENOISE_MAIN_GAMMA;Gamma TP_DIRPYRDENOISE_MAIN_GAMMA_TOOLTIP;Gamma fait varier la quantité de réduction de bruit sur l'échelle des tons. Les plus petites valeurs cibleront les ombres, les plus hautes valeurs cibleront les tons les plus clairs. -TP_DIRPYRDENOISE_MAIN_MODE;Qualité -TP_DIRPYRDENOISE_MAIN_MODE_AGGRESSIVE;Haut -TP_DIRPYRDENOISE_MAIN_MODE_CONSERVATIVE;Standard -TP_DIRPYRDENOISE_MAIN_MODE_TOOLTIP;La qualité peut être adapté à la trame du bruit. Régler sur "haut" augmentera l'effet de la réduction de bruit au prix d'un temps de traitement plus long. -TP_DIRPYRDENOISE_MEDIAN_METHOD;Méthode +TP_DIRPYRDENOISE_MAIN_MODE;Mode +TP_DIRPYRDENOISE_MAIN_MODE_AGGRESSIVE;Agressif +TP_DIRPYRDENOISE_MAIN_MODE_CONSERVATIVE;Conservatif +TP_DIRPYRDENOISE_MAIN_MODE_TOOLTIP;"Conservatif" préserve les motifs chromatiques de basse fréquence tandis que "agressif" les efface. +TP_DIRPYRDENOISE_MEDIAN_METHOD;Méthode médiane TP_DIRPYRDENOISE_MEDIAN_METHOD_CHROMINANCE;Chroma uniquement TP_DIRPYRDENOISE_MEDIAN_METHOD_LAB;L*a*b* TP_DIRPYRDENOISE_MEDIAN_METHOD_LABEL;Filtre Médian @@ -2205,7 +2205,9 @@ ZOOMPANEL_ZOOMOUT;Zoom Arrière\nRaccourci: - !HISTORY_MSG_489;DRC - Threshold !HISTORY_MSG_490;DRC - Amount !HISTORY_MSG_CLAMPOOG;Out-of-gamut color clipping +!HISTORY_MSG_DUALDEMOSAIC_CONTRAST;AMaZE+VNG4 - Contrast threshold !HISTORY_MSG_MICROCONTRAST_CONTRAST;Microcontrast - Contrast threshold +!HISTORY_MSG_PIXELSHIFT_DEMOSAIC;PS - Demosaic method for motion !HISTORY_MSG_PREPROCESS_LINEDENOISE_DIRECTION;Line noise filter direction !HISTORY_MSG_PREPROCESS_PDAFLINESFILTER;PDAF lines filter !HISTORY_MSG_PRSHARPEN_CONTRAST;PRS - Contrast threshold @@ -2226,6 +2228,10 @@ ZOOMPANEL_ZOOMOUT;Zoom Arrière\nRaccourci: - !TP_PREPROCESS_LINEDENOISE_DIRECTION_VERTICAL;Vertical !TP_PREPROCESS_PDAFLINESFILTER;PDAF lines filter !TP_PREPROCESS_PDAFLINESFILTER_TOOLTIP;Tries to suppress stripe noise caused by on-sensor PDAF pixels, occurring with some Sony mirrorless cameras on some backlit scenes with visible flare. +!TP_RAW_4PASS;4-Pass +!TP_RAW_AMAZEVNG4;AMaZE+VNG4 +!TP_RAW_DUALDEMOSAICCONTRAST;Contrast threshold +!TP_RAW_PIXELSHIFTDMETHOD;Demosaic method for motion !TP_RAW_PIXELSHIFTEPERISO;Sensitivity !TP_RAW_PIXELSHIFTEPERISO_TOOLTIP;The default value of 0 should work fine for base ISO.\nHigher values increase sensitivity of motion detection.\nChange in small steps and watch the motion mask while changing.\nIncrease sensitivity for underexposed or high ISO images. !TP_RAW_PIXELSHIFTSHOWMOTION_TOOLTIP;Overlays the image with a green mask showing the regions with motion. From f7d3fd1a48f511946ea1527e65b7fbad7136f9f7 Mon Sep 17 00:00:00 2001 From: Morgan Hardwood Date: Wed, 13 Jun 2018 10:42:35 +0200 Subject: [PATCH 37/42] generateTranslationDiffs --- rtdata/languages/Catala | 6 +++++ rtdata/languages/Chinese (Simplified) | 6 +++++ rtdata/languages/Chinese (Traditional) | 6 +++++ rtdata/languages/Czech | 6 +++++ rtdata/languages/Dansk | 6 +++++ rtdata/languages/Deutsch | 24 ++++++++++++------- rtdata/languages/English (UK) | 6 +++++ rtdata/languages/English (US) | 6 +++++ rtdata/languages/Espanol | 6 +++++ rtdata/languages/Euskara | 6 +++++ rtdata/languages/Greek | 6 +++++ rtdata/languages/Hebrew | 6 +++++ rtdata/languages/Italiano | 6 +++++ rtdata/languages/Latvian | 6 +++++ rtdata/languages/Magyar | 6 +++++ rtdata/languages/Nederlands | 6 +++++ rtdata/languages/Norsk BM | 6 +++++ rtdata/languages/Polish | 6 +++++ rtdata/languages/Polish (Latin Characters) | 6 +++++ rtdata/languages/Portugues (Brasil) | 6 +++++ rtdata/languages/Russian | 6 +++++ rtdata/languages/Serbian (Cyrilic Characters) | 6 +++++ rtdata/languages/Serbian (Latin Characters) | 6 +++++ rtdata/languages/Slovak | 6 +++++ rtdata/languages/Suomi | 6 +++++ rtdata/languages/Swedish | 6 +++++ rtdata/languages/Turkish | 6 +++++ 27 files changed, 171 insertions(+), 9 deletions(-) diff --git a/rtdata/languages/Catala b/rtdata/languages/Catala index 42d26f21f..8f928ebc7 100644 --- a/rtdata/languages/Catala +++ b/rtdata/languages/Catala @@ -1321,6 +1321,7 @@ ZOOMPANEL_ZOOMOUT;Allunya\nDrecera: - !HISTORY_MSG_493;L*a*b* Adjustments !HISTORY_MSG_CLAMPOOG;Out-of-gamut color clipping !HISTORY_MSG_COLORTONING_LABGRID_VALUE;CT - Color correction +!HISTORY_MSG_DUALDEMOSAIC_CONTRAST;AMaZE+VNG4 - Contrast threshold !HISTORY_MSG_HISTMATCHING;Auto-Matched Tone Curve !HISTORY_MSG_LOCALCONTRAST_AMOUNT;Local Contrast - Amount !HISTORY_MSG_LOCALCONTRAST_DARKNESS;Local Contrast - Darkness @@ -1329,6 +1330,7 @@ ZOOMPANEL_ZOOMOUT;Allunya\nDrecera: - !HISTORY_MSG_LOCALCONTRAST_RADIUS;Local Contrast - Radius !HISTORY_MSG_METADATA_MODE;Metadata copy mode !HISTORY_MSG_MICROCONTRAST_CONTRAST;Microcontrast - Contrast threshold +!HISTORY_MSG_PIXELSHIFT_DEMOSAIC;PS - Demosaic method for motion !HISTORY_MSG_PREPROCESS_LINEDENOISE_DIRECTION;Line noise filter direction !HISTORY_MSG_PREPROCESS_PDAFLINESFILTER;PDAF lines filter !HISTORY_MSG_PRSHARPEN_CONTRAST;PRS - Contrast threshold @@ -1894,12 +1896,15 @@ ZOOMPANEL_ZOOMOUT;Allunya\nDrecera: - !TP_RAWEXPOS_RGB;Red, Green, Blue !TP_RAW_1PASSMEDIUM;1-Pass (Medium) !TP_RAW_3PASSBEST;3-Pass (Best) +!TP_RAW_4PASS;4-Pass !TP_RAW_AHD;AHD !TP_RAW_AMAZE;AMaZE +!TP_RAW_AMAZEVNG4;AMaZE+VNG4 !TP_RAW_DCB;DCB !TP_RAW_DMETHOD_PROGRESSBAR;%1 demosaicing... !TP_RAW_DMETHOD_PROGRESSBAR_REFINE;Demosaicing refinement... !TP_RAW_DMETHOD_TOOLTIP;Note: IGV and LMMSE are dedicated to high ISO images to aid in noise reduction without leading to maze patterns, posterization or a washed-out look.\nPixel Shift is for Pentax/Sony Pixel Shift files. It falls back to AMaZE for non-Pixel Shift files. +!TP_RAW_DUALDEMOSAICCONTRAST;Contrast threshold !TP_RAW_EAHD;EAHD !TP_RAW_FAST;Fast !TP_RAW_HD;Threshold @@ -1915,6 +1920,7 @@ ZOOMPANEL_ZOOMOUT;Allunya\nDrecera: - !TP_RAW_NONE;None (Shows sensor pattern) !TP_RAW_PIXELSHIFT;Pixel Shift !TP_RAW_PIXELSHIFTBLUR;Blur motion mask +!TP_RAW_PIXELSHIFTDMETHOD;Demosaic method for motion !TP_RAW_PIXELSHIFTEPERISO;Sensitivity !TP_RAW_PIXELSHIFTEPERISO_TOOLTIP;The default value of 0 should work fine for base ISO.\nHigher values increase sensitivity of motion detection.\nChange in small steps and watch the motion mask while changing.\nIncrease sensitivity for underexposed or high ISO images. !TP_RAW_PIXELSHIFTEQUALBRIGHT;Equalize brightness of frames diff --git a/rtdata/languages/Chinese (Simplified) b/rtdata/languages/Chinese (Simplified) index d19c9d366..b4404728f 100644 --- a/rtdata/languages/Chinese (Simplified) +++ b/rtdata/languages/Chinese (Simplified) @@ -1428,6 +1428,7 @@ ZOOMPANEL_ZOOMOUT;缩放拉远\n快捷键: - !HISTORY_MSG_493;L*a*b* Adjustments !HISTORY_MSG_CLAMPOOG;Out-of-gamut color clipping !HISTORY_MSG_COLORTONING_LABGRID_VALUE;CT - Color correction +!HISTORY_MSG_DUALDEMOSAIC_CONTRAST;AMaZE+VNG4 - Contrast threshold !HISTORY_MSG_HISTMATCHING;Auto-Matched Tone Curve !HISTORY_MSG_LOCALCONTRAST_AMOUNT;Local Contrast - Amount !HISTORY_MSG_LOCALCONTRAST_DARKNESS;Local Contrast - Darkness @@ -1436,6 +1437,7 @@ ZOOMPANEL_ZOOMOUT;缩放拉远\n快捷键: - !HISTORY_MSG_LOCALCONTRAST_RADIUS;Local Contrast - Radius !HISTORY_MSG_METADATA_MODE;Metadata copy mode !HISTORY_MSG_MICROCONTRAST_CONTRAST;Microcontrast - Contrast threshold +!HISTORY_MSG_PIXELSHIFT_DEMOSAIC;PS - Demosaic method for motion !HISTORY_MSG_PREPROCESS_LINEDENOISE_DIRECTION;Line noise filter direction !HISTORY_MSG_PREPROCESS_PDAFLINESFILTER;PDAF lines filter !HISTORY_MSG_PRSHARPEN_CONTRAST;PRS - Contrast threshold @@ -1867,8 +1869,10 @@ ZOOMPANEL_ZOOMOUT;缩放拉远\n快捷键: - !TP_RAWEXPOS_TWOGREEN;Link greens !TP_RAW_1PASSMEDIUM;1-Pass (Medium) !TP_RAW_3PASSBEST;3-Pass (Best) +!TP_RAW_4PASS;4-Pass !TP_RAW_AHD;AHD !TP_RAW_AMAZE;AMaZE +!TP_RAW_AMAZEVNG4;AMaZE+VNG4 !TP_RAW_DCB;DCB !TP_RAW_DCBENHANCE;DCB enhancement !TP_RAW_DCBITERATIONS;Number of DCB iterations @@ -1876,6 +1880,7 @@ ZOOMPANEL_ZOOMOUT;缩放拉远\n快捷键: - !TP_RAW_DMETHOD_PROGRESSBAR;%1 demosaicing... !TP_RAW_DMETHOD_PROGRESSBAR_REFINE;Demosaicing refinement... !TP_RAW_DMETHOD_TOOLTIP;Note: IGV and LMMSE are dedicated to high ISO images to aid in noise reduction without leading to maze patterns, posterization or a washed-out look.\nPixel Shift is for Pentax/Sony Pixel Shift files. It falls back to AMaZE for non-Pixel Shift files. +!TP_RAW_DUALDEMOSAICCONTRAST;Contrast threshold !TP_RAW_EAHD;EAHD !TP_RAW_FALSECOLOR;False color suppression steps !TP_RAW_FAST;Fast @@ -1893,6 +1898,7 @@ ZOOMPANEL_ZOOMOUT;缩放拉远\n快捷键: - !TP_RAW_NONE;None (Shows sensor pattern) !TP_RAW_PIXELSHIFT;Pixel Shift !TP_RAW_PIXELSHIFTBLUR;Blur motion mask +!TP_RAW_PIXELSHIFTDMETHOD;Demosaic method for motion !TP_RAW_PIXELSHIFTEPERISO;Sensitivity !TP_RAW_PIXELSHIFTEPERISO_TOOLTIP;The default value of 0 should work fine for base ISO.\nHigher values increase sensitivity of motion detection.\nChange in small steps and watch the motion mask while changing.\nIncrease sensitivity for underexposed or high ISO images. !TP_RAW_PIXELSHIFTEQUALBRIGHT;Equalize brightness of frames diff --git a/rtdata/languages/Chinese (Traditional) b/rtdata/languages/Chinese (Traditional) index dbb316209..cdb0bc822 100644 --- a/rtdata/languages/Chinese (Traditional) +++ b/rtdata/languages/Chinese (Traditional) @@ -983,6 +983,7 @@ TP_WBALANCE_TEMPERATURE;色溫 !HISTORY_MSG_493;L*a*b* Adjustments !HISTORY_MSG_CLAMPOOG;Out-of-gamut color clipping !HISTORY_MSG_COLORTONING_LABGRID_VALUE;CT - Color correction +!HISTORY_MSG_DUALDEMOSAIC_CONTRAST;AMaZE+VNG4 - Contrast threshold !HISTORY_MSG_HISTMATCHING;Auto-Matched Tone Curve !HISTORY_MSG_LOCALCONTRAST_AMOUNT;Local Contrast - Amount !HISTORY_MSG_LOCALCONTRAST_DARKNESS;Local Contrast - Darkness @@ -991,6 +992,7 @@ TP_WBALANCE_TEMPERATURE;色溫 !HISTORY_MSG_LOCALCONTRAST_RADIUS;Local Contrast - Radius !HISTORY_MSG_METADATA_MODE;Metadata copy mode !HISTORY_MSG_MICROCONTRAST_CONTRAST;Microcontrast - Contrast threshold +!HISTORY_MSG_PIXELSHIFT_DEMOSAIC;PS - Demosaic method for motion !HISTORY_MSG_PREPROCESS_LINEDENOISE_DIRECTION;Line noise filter direction !HISTORY_MSG_PREPROCESS_PDAFLINESFILTER;PDAF lines filter !HISTORY_MSG_PRSHARPEN_CONTRAST;PRS - Contrast threshold @@ -1815,8 +1817,10 @@ TP_WBALANCE_TEMPERATURE;色溫 !TP_RAWEXPOS_TWOGREEN;Link greens !TP_RAW_1PASSMEDIUM;1-Pass (Medium) !TP_RAW_3PASSBEST;3-Pass (Best) +!TP_RAW_4PASS;4-Pass !TP_RAW_AHD;AHD !TP_RAW_AMAZE;AMaZE +!TP_RAW_AMAZEVNG4;AMaZE+VNG4 !TP_RAW_DCB;DCB !TP_RAW_DCBENHANCE;DCB enhancement !TP_RAW_DCBITERATIONS;Number of DCB iterations @@ -1824,6 +1828,7 @@ TP_WBALANCE_TEMPERATURE;色溫 !TP_RAW_DMETHOD_PROGRESSBAR;%1 demosaicing... !TP_RAW_DMETHOD_PROGRESSBAR_REFINE;Demosaicing refinement... !TP_RAW_DMETHOD_TOOLTIP;Note: IGV and LMMSE are dedicated to high ISO images to aid in noise reduction without leading to maze patterns, posterization or a washed-out look.\nPixel Shift is for Pentax/Sony Pixel Shift files. It falls back to AMaZE for non-Pixel Shift files. +!TP_RAW_DUALDEMOSAICCONTRAST;Contrast threshold !TP_RAW_EAHD;EAHD !TP_RAW_FALSECOLOR;False color suppression steps !TP_RAW_FAST;Fast @@ -1841,6 +1846,7 @@ TP_WBALANCE_TEMPERATURE;色溫 !TP_RAW_NONE;None (Shows sensor pattern) !TP_RAW_PIXELSHIFT;Pixel Shift !TP_RAW_PIXELSHIFTBLUR;Blur motion mask +!TP_RAW_PIXELSHIFTDMETHOD;Demosaic method for motion !TP_RAW_PIXELSHIFTEPERISO;Sensitivity !TP_RAW_PIXELSHIFTEPERISO_TOOLTIP;The default value of 0 should work fine for base ISO.\nHigher values increase sensitivity of motion detection.\nChange in small steps and watch the motion mask while changing.\nIncrease sensitivity for underexposed or high ISO images. !TP_RAW_PIXELSHIFTEQUALBRIGHT;Equalize brightness of frames diff --git a/rtdata/languages/Czech b/rtdata/languages/Czech index f5a4c16c3..4b88d089c 100644 --- a/rtdata/languages/Czech +++ b/rtdata/languages/Czech @@ -2233,7 +2233,9 @@ ZOOMPANEL_ZOOMOUT;Oddálit\nZkratka: - !HISTORY_MSG_488;Dynamic Range Compression !HISTORY_MSG_489;DRC - Threshold !HISTORY_MSG_490;DRC - Amount +!HISTORY_MSG_DUALDEMOSAIC_CONTRAST;AMaZE+VNG4 - Contrast threshold !HISTORY_MSG_MICROCONTRAST_CONTRAST;Microcontrast - Contrast threshold +!HISTORY_MSG_PIXELSHIFT_DEMOSAIC;PS - Demosaic method for motion !HISTORY_MSG_PRSHARPEN_CONTRAST;PRS - Contrast threshold !HISTORY_MSG_SHARPENING_CONTRAST;Sharpening - Contrast threshold !HISTORY_MSG_TM_FATTAL_ANCHOR;DRC - Anchor @@ -2242,6 +2244,10 @@ ZOOMPANEL_ZOOMOUT;Oddálit\nZkratka: - !SAMPLEFORMAT_64;32-bit floating-point !TP_BWMIX_MIXC;Channel Mixer !TP_BWMIX_NEUTRAL;Reset +!TP_RAW_4PASS;4-Pass +!TP_RAW_AMAZEVNG4;AMaZE+VNG4 +!TP_RAW_DUALDEMOSAICCONTRAST;Contrast threshold +!TP_RAW_PIXELSHIFTDMETHOD;Demosaic method for motion !TP_SHARPENING_CONTRAST;Contrast threshold !TP_SHARPENMICRO_CONTRAST;Contrast threshold !TP_TM_FATTAL_AMOUNT;Amount diff --git a/rtdata/languages/Dansk b/rtdata/languages/Dansk index f23bce005..48871b32a 100644 --- a/rtdata/languages/Dansk +++ b/rtdata/languages/Dansk @@ -978,6 +978,7 @@ TP_WBALANCE_TEMPERATURE;Temperatur !HISTORY_MSG_493;L*a*b* Adjustments !HISTORY_MSG_CLAMPOOG;Out-of-gamut color clipping !HISTORY_MSG_COLORTONING_LABGRID_VALUE;CT - Color correction +!HISTORY_MSG_DUALDEMOSAIC_CONTRAST;AMaZE+VNG4 - Contrast threshold !HISTORY_MSG_HISTMATCHING;Auto-Matched Tone Curve !HISTORY_MSG_LOCALCONTRAST_AMOUNT;Local Contrast - Amount !HISTORY_MSG_LOCALCONTRAST_DARKNESS;Local Contrast - Darkness @@ -986,6 +987,7 @@ TP_WBALANCE_TEMPERATURE;Temperatur !HISTORY_MSG_LOCALCONTRAST_RADIUS;Local Contrast - Radius !HISTORY_MSG_METADATA_MODE;Metadata copy mode !HISTORY_MSG_MICROCONTRAST_CONTRAST;Microcontrast - Contrast threshold +!HISTORY_MSG_PIXELSHIFT_DEMOSAIC;PS - Demosaic method for motion !HISTORY_MSG_PREPROCESS_LINEDENOISE_DIRECTION;Line noise filter direction !HISTORY_MSG_PREPROCESS_PDAFLINESFILTER;PDAF lines filter !HISTORY_MSG_PRSHARPEN_CONTRAST;PRS - Contrast threshold @@ -1812,14 +1814,17 @@ TP_WBALANCE_TEMPERATURE;Temperatur !TP_RAWEXPOS_TWOGREEN;Link greens !TP_RAW_1PASSMEDIUM;1-Pass (Medium) !TP_RAW_3PASSBEST;3-Pass (Best) +!TP_RAW_4PASS;4-Pass !TP_RAW_AHD;AHD !TP_RAW_AMAZE;AMaZE +!TP_RAW_AMAZEVNG4;AMaZE+VNG4 !TP_RAW_DCB;DCB !TP_RAW_DCBENHANCE;DCB enhancement !TP_RAW_DCBITERATIONS;Number of DCB iterations !TP_RAW_DMETHOD_PROGRESSBAR;%1 demosaicing... !TP_RAW_DMETHOD_PROGRESSBAR_REFINE;Demosaicing refinement... !TP_RAW_DMETHOD_TOOLTIP;Note: IGV and LMMSE are dedicated to high ISO images to aid in noise reduction without leading to maze patterns, posterization or a washed-out look.\nPixel Shift is for Pentax/Sony Pixel Shift files. It falls back to AMaZE for non-Pixel Shift files. +!TP_RAW_DUALDEMOSAICCONTRAST;Contrast threshold !TP_RAW_EAHD;EAHD !TP_RAW_FAST;Fast !TP_RAW_HD;Threshold @@ -1836,6 +1841,7 @@ TP_WBALANCE_TEMPERATURE;Temperatur !TP_RAW_NONE;None (Shows sensor pattern) !TP_RAW_PIXELSHIFT;Pixel Shift !TP_RAW_PIXELSHIFTBLUR;Blur motion mask +!TP_RAW_PIXELSHIFTDMETHOD;Demosaic method for motion !TP_RAW_PIXELSHIFTEPERISO;Sensitivity !TP_RAW_PIXELSHIFTEPERISO_TOOLTIP;The default value of 0 should work fine for base ISO.\nHigher values increase sensitivity of motion detection.\nChange in small steps and watch the motion mask while changing.\nIncrease sensitivity for underexposed or high ISO images. !TP_RAW_PIXELSHIFTEQUALBRIGHT;Equalize brightness of frames diff --git a/rtdata/languages/Deutsch b/rtdata/languages/Deutsch index 75aa4a42a..d696da4dd 100644 --- a/rtdata/languages/Deutsch +++ b/rtdata/languages/Deutsch @@ -776,6 +776,9 @@ HISTORY_MSG_484;(CIECAM02) - Szene\nAuto Yb% HISTORY_MSG_485;(Objektivkorrektur)\nProfil HISTORY_MSG_486;(Objektivkorrektur)\nProfil - Kamera HISTORY_MSG_487;(Objektivkorrektur)\nProfil - Objektiv +HISTORY_MSG_488;(Dynamikkompression) +HISTORY_MSG_489;(Dynamikkompression)\nSchwelle +HISTORY_MSG_490;(Dynamikkompression)\nIntensität HISTORY_MSG_491;(Weißabgleich) HISTORY_MSG_492;(RGB-Kurven) HISTORY_MSG_493;(L*a*b*) @@ -793,6 +796,7 @@ HISTORY_MSG_PREPROCESS_LINEDENOISE_DIRECTION;(Sensor-Matrix)\nVorverarbeitung\nR HISTORY_MSG_PREPROCESS_PDAFLINESFILTER;(Sensor-Matrix)\nVorverarbeitung\nPDAF-Zeilenfilter HISTORY_MSG_PRSHARPEN_CONTRAST;(Skalieren) - Schärfen\nKontrastschwelle HISTORY_MSG_SHARPENING_CONTRAST;(Schärfung)\nKontrastschwelle +HISTORY_MSG_TM_FATTAL_ANCHOR;(Dynamikkompression)\nHelligkeitsverschiebung HISTORY_NEWSNAPSHOT;Hinzufügen HISTORY_NEWSNAPSHOT_TOOLTIP;Taste: Alt + s HISTORY_SNAPSHOT;Schnappschuss @@ -1005,6 +1009,7 @@ PARTIALPASTE_SHADOWSHIGHLIGHTS;Schatten/Lichter PARTIALPASTE_SHARPENEDGE;Kantenschärfung PARTIALPASTE_SHARPENING;Schärfung PARTIALPASTE_SHARPENMICRO;Mikrokontrast +PARTIALPASTE_TM_FATTAL;Dynamikkompression PARTIALPASTE_VIBRANCE;Dynamik PARTIALPASTE_VIGNETTING;Vignettierungskorrektur PARTIALPASTE_WAVELETGROUP;Wavelet @@ -2037,6 +2042,10 @@ TP_SHARPENMICRO_CONTRAST;Kontrastschwelle TP_SHARPENMICRO_LABEL;Mikrokontrast TP_SHARPENMICRO_MATRIX;3×3-Matrix statt 5×5-Matrix TP_SHARPENMICRO_UNIFORMITY;Gleichmäßigkeit +TP_TM_FATTAL_AMOUNT;Intensität +TP_TM_FATTAL_ANCHOR;Helligkeitsverschiebung +TP_TM_FATTAL_LABEL;Dynamikkompression +TP_TM_FATTAL_THRESHOLD;Schwelle TP_VIBRANCE_AVOIDCOLORSHIFT;Farbverschiebungen vermeiden TP_VIBRANCE_CURVEEDITOR_SKINTONES;HH TP_VIBRANCE_CURVEEDITOR_SKINTONES_LABEL;Hautfarbtöne @@ -2284,12 +2293,9 @@ ZOOMPANEL_ZOOMOUT;Herauszoomen\nTaste: - ! Untranslated keys follow; remove the ! prefix after an entry is translated. !!!!!!!!!!!!!!!!!!!!!!!!! -HISTORY_MSG_488;(Dynamikkompression) -HISTORY_MSG_489;(Dynamikkompression)\nSchwelle -HISTORY_MSG_490;(Dynamikkompression)\nIntensität -HISTORY_MSG_TM_FATTAL_ANCHOR;(Dynamikkompression)\nHelligkeitsverschiebung -PARTIALPASTE_TM_FATTAL;Dynamikkompression -TP_TM_FATTAL_AMOUNT;Intensität -TP_TM_FATTAL_ANCHOR;Helligkeitsverschiebung -TP_TM_FATTAL_LABEL;Dynamikkompression -TP_TM_FATTAL_THRESHOLD;Schwelle +!HISTORY_MSG_DUALDEMOSAIC_CONTRAST;AMaZE+VNG4 - Contrast threshold +!HISTORY_MSG_PIXELSHIFT_DEMOSAIC;PS - Demosaic method for motion +!TP_RAW_4PASS;4-Pass +!TP_RAW_AMAZEVNG4;AMaZE+VNG4 +!TP_RAW_DUALDEMOSAICCONTRAST;Contrast threshold +!TP_RAW_PIXELSHIFTDMETHOD;Demosaic method for motion diff --git a/rtdata/languages/English (UK) b/rtdata/languages/English (UK) index 3df222ced..9ba753ef5 100644 --- a/rtdata/languages/English (UK) +++ b/rtdata/languages/English (UK) @@ -814,6 +814,7 @@ TP_WBALANCE_EQBLUERED_TOOLTIP;Allows to deviate from the normal behaviour of "wh !HISTORY_MSG_491;White Balance !HISTORY_MSG_492;RGB Curves !HISTORY_MSG_493;L*a*b* Adjustments +!HISTORY_MSG_DUALDEMOSAIC_CONTRAST;AMaZE+VNG4 - Contrast threshold !HISTORY_MSG_HISTMATCHING;Auto-Matched Tone Curve !HISTORY_MSG_LOCALCONTRAST_AMOUNT;Local Contrast - Amount !HISTORY_MSG_LOCALCONTRAST_DARKNESS;Local Contrast - Darkness @@ -822,6 +823,7 @@ TP_WBALANCE_EQBLUERED_TOOLTIP;Allows to deviate from the normal behaviour of "wh !HISTORY_MSG_LOCALCONTRAST_RADIUS;Local Contrast - Radius !HISTORY_MSG_METADATA_MODE;Metadata copy mode !HISTORY_MSG_MICROCONTRAST_CONTRAST;Microcontrast - Contrast threshold +!HISTORY_MSG_PIXELSHIFT_DEMOSAIC;PS - Demosaic method for motion !HISTORY_MSG_PREPROCESS_LINEDENOISE_DIRECTION;Line noise filter direction !HISTORY_MSG_PREPROCESS_PDAFLINESFILTER;PDAF lines filter !HISTORY_MSG_PRSHARPEN_CONTRAST;PRS - Contrast threshold @@ -1775,8 +1777,10 @@ TP_WBALANCE_EQBLUERED_TOOLTIP;Allows to deviate from the normal behaviour of "wh !TP_RAWEXPOS_TWOGREEN;Link greens !TP_RAW_1PASSMEDIUM;1-Pass (Medium) !TP_RAW_3PASSBEST;3-Pass (Best) +!TP_RAW_4PASS;4-Pass !TP_RAW_AHD;AHD !TP_RAW_AMAZE;AMaZE +!TP_RAW_AMAZEVNG4;AMaZE+VNG4 !TP_RAW_DCB;DCB !TP_RAW_DCBENHANCE;DCB enhancement !TP_RAW_DCBITERATIONS;Number of DCB iterations @@ -1784,6 +1788,7 @@ TP_WBALANCE_EQBLUERED_TOOLTIP;Allows to deviate from the normal behaviour of "wh !TP_RAW_DMETHOD_PROGRESSBAR;%1 demosaicing... !TP_RAW_DMETHOD_PROGRESSBAR_REFINE;Demosaicing refinement... !TP_RAW_DMETHOD_TOOLTIP;Note: IGV and LMMSE are dedicated to high ISO images to aid in noise reduction without leading to maze patterns, posterization or a washed-out look.\nPixel Shift is for Pentax/Sony Pixel Shift files. It falls back to AMaZE for non-Pixel Shift files. +!TP_RAW_DUALDEMOSAICCONTRAST;Contrast threshold !TP_RAW_EAHD;EAHD !TP_RAW_FAST;Fast !TP_RAW_HD;Threshold @@ -1800,6 +1805,7 @@ TP_WBALANCE_EQBLUERED_TOOLTIP;Allows to deviate from the normal behaviour of "wh !TP_RAW_NONE;None (Shows sensor pattern) !TP_RAW_PIXELSHIFT;Pixel Shift !TP_RAW_PIXELSHIFTBLUR;Blur motion mask +!TP_RAW_PIXELSHIFTDMETHOD;Demosaic method for motion !TP_RAW_PIXELSHIFTEPERISO;Sensitivity !TP_RAW_PIXELSHIFTEPERISO_TOOLTIP;The default value of 0 should work fine for base ISO.\nHigher values increase sensitivity of motion detection.\nChange in small steps and watch the motion mask while changing.\nIncrease sensitivity for underexposed or high ISO images. !TP_RAW_PIXELSHIFTEQUALBRIGHT;Equalize brightness of frames diff --git a/rtdata/languages/English (US) b/rtdata/languages/English (US) index e639b0866..88254c317 100644 --- a/rtdata/languages/English (US) +++ b/rtdata/languages/English (US) @@ -728,6 +728,7 @@ !HISTORY_MSG_493;L*a*b* Adjustments !HISTORY_MSG_CLAMPOOG;Out-of-gamut color clipping !HISTORY_MSG_COLORTONING_LABGRID_VALUE;CT - Color correction +!HISTORY_MSG_DUALDEMOSAIC_CONTRAST;AMaZE+VNG4 - Contrast threshold !HISTORY_MSG_HISTMATCHING;Auto-Matched Tone Curve !HISTORY_MSG_LOCALCONTRAST_AMOUNT;Local Contrast - Amount !HISTORY_MSG_LOCALCONTRAST_DARKNESS;Local Contrast - Darkness @@ -736,6 +737,7 @@ !HISTORY_MSG_LOCALCONTRAST_RADIUS;Local Contrast - Radius !HISTORY_MSG_METADATA_MODE;Metadata copy mode !HISTORY_MSG_MICROCONTRAST_CONTRAST;Microcontrast - Contrast threshold +!HISTORY_MSG_PIXELSHIFT_DEMOSAIC;PS - Demosaic method for motion !HISTORY_MSG_PREPROCESS_LINEDENOISE_DIRECTION;Line noise filter direction !HISTORY_MSG_PREPROCESS_PDAFLINESFILTER;PDAF lines filter !HISTORY_MSG_PRSHARPEN_CONTRAST;PRS - Contrast threshold @@ -1762,8 +1764,10 @@ !TP_RAWEXPOS_TWOGREEN;Link greens !TP_RAW_1PASSMEDIUM;1-Pass (Medium) !TP_RAW_3PASSBEST;3-Pass (Best) +!TP_RAW_4PASS;4-Pass !TP_RAW_AHD;AHD !TP_RAW_AMAZE;AMaZE +!TP_RAW_AMAZEVNG4;AMaZE+VNG4 !TP_RAW_DCB;DCB !TP_RAW_DCBENHANCE;DCB enhancement !TP_RAW_DCBITERATIONS;Number of DCB iterations @@ -1771,6 +1775,7 @@ !TP_RAW_DMETHOD_PROGRESSBAR;%1 demosaicing... !TP_RAW_DMETHOD_PROGRESSBAR_REFINE;Demosaicing refinement... !TP_RAW_DMETHOD_TOOLTIP;Note: IGV and LMMSE are dedicated to high ISO images to aid in noise reduction without leading to maze patterns, posterization or a washed-out look.\nPixel Shift is for Pentax/Sony Pixel Shift files. It falls back to AMaZE for non-Pixel Shift files. +!TP_RAW_DUALDEMOSAICCONTRAST;Contrast threshold !TP_RAW_EAHD;EAHD !TP_RAW_FALSECOLOR;False color suppression steps !TP_RAW_FAST;Fast @@ -1788,6 +1793,7 @@ !TP_RAW_NONE;None (Shows sensor pattern) !TP_RAW_PIXELSHIFT;Pixel Shift !TP_RAW_PIXELSHIFTBLUR;Blur motion mask +!TP_RAW_PIXELSHIFTDMETHOD;Demosaic method for motion !TP_RAW_PIXELSHIFTEPERISO;Sensitivity !TP_RAW_PIXELSHIFTEPERISO_TOOLTIP;The default value of 0 should work fine for base ISO.\nHigher values increase sensitivity of motion detection.\nChange in small steps and watch the motion mask while changing.\nIncrease sensitivity for underexposed or high ISO images. !TP_RAW_PIXELSHIFTEQUALBRIGHT;Equalize brightness of frames diff --git a/rtdata/languages/Espanol b/rtdata/languages/Espanol index c20a54871..5f4866261 100644 --- a/rtdata/languages/Espanol +++ b/rtdata/languages/Espanol @@ -1708,6 +1708,7 @@ ZOOMPANEL_ZOOMOUT;Reducir Zoom\nAtajo: - !HISTORY_MSG_493;L*a*b* Adjustments !HISTORY_MSG_CLAMPOOG;Out-of-gamut color clipping !HISTORY_MSG_COLORTONING_LABGRID_VALUE;CT - Color correction +!HISTORY_MSG_DUALDEMOSAIC_CONTRAST;AMaZE+VNG4 - Contrast threshold !HISTORY_MSG_HISTMATCHING;Auto-Matched Tone Curve !HISTORY_MSG_LOCALCONTRAST_AMOUNT;Local Contrast - Amount !HISTORY_MSG_LOCALCONTRAST_DARKNESS;Local Contrast - Darkness @@ -1716,6 +1717,7 @@ ZOOMPANEL_ZOOMOUT;Reducir Zoom\nAtajo: - !HISTORY_MSG_LOCALCONTRAST_RADIUS;Local Contrast - Radius !HISTORY_MSG_METADATA_MODE;Metadata copy mode !HISTORY_MSG_MICROCONTRAST_CONTRAST;Microcontrast - Contrast threshold +!HISTORY_MSG_PIXELSHIFT_DEMOSAIC;PS - Demosaic method for motion !HISTORY_MSG_PREPROCESS_LINEDENOISE_DIRECTION;Line noise filter direction !HISTORY_MSG_PREPROCESS_PDAFLINESFILTER;PDAF lines filter !HISTORY_MSG_PRSHARPEN_CONTRAST;PRS - Contrast threshold @@ -1977,9 +1979,12 @@ ZOOMPANEL_ZOOMOUT;Reducir Zoom\nAtajo: - !TP_RAWCACORR_CASTR;Strength !TP_RAW_1PASSMEDIUM;1-Pass (Medium) !TP_RAW_3PASSBEST;3-Pass (Best) +!TP_RAW_4PASS;4-Pass !TP_RAW_AHD;AHD !TP_RAW_AMAZE;AMaZE +!TP_RAW_AMAZEVNG4;AMaZE+VNG4 !TP_RAW_DCB;DCB +!TP_RAW_DUALDEMOSAICCONTRAST;Contrast threshold !TP_RAW_EAHD;EAHD !TP_RAW_FAST;Fast !TP_RAW_HD;Threshold @@ -1993,6 +1998,7 @@ ZOOMPANEL_ZOOMOUT;Reducir Zoom\nAtajo: - !TP_RAW_NONE;None (Shows sensor pattern) !TP_RAW_PIXELSHIFT;Pixel Shift !TP_RAW_PIXELSHIFTBLUR;Blur motion mask +!TP_RAW_PIXELSHIFTDMETHOD;Demosaic method for motion !TP_RAW_PIXELSHIFTEPERISO;Sensitivity !TP_RAW_PIXELSHIFTEPERISO_TOOLTIP;The default value of 0 should work fine for base ISO.\nHigher values increase sensitivity of motion detection.\nChange in small steps and watch the motion mask while changing.\nIncrease sensitivity for underexposed or high ISO images. !TP_RAW_PIXELSHIFTEQUALBRIGHT;Equalize brightness of frames diff --git a/rtdata/languages/Euskara b/rtdata/languages/Euskara index b1a005afe..59a73eee7 100644 --- a/rtdata/languages/Euskara +++ b/rtdata/languages/Euskara @@ -979,6 +979,7 @@ TP_WBALANCE_TEMPERATURE;Tenperatura !HISTORY_MSG_493;L*a*b* Adjustments !HISTORY_MSG_CLAMPOOG;Out-of-gamut color clipping !HISTORY_MSG_COLORTONING_LABGRID_VALUE;CT - Color correction +!HISTORY_MSG_DUALDEMOSAIC_CONTRAST;AMaZE+VNG4 - Contrast threshold !HISTORY_MSG_HISTMATCHING;Auto-Matched Tone Curve !HISTORY_MSG_LOCALCONTRAST_AMOUNT;Local Contrast - Amount !HISTORY_MSG_LOCALCONTRAST_DARKNESS;Local Contrast - Darkness @@ -987,6 +988,7 @@ TP_WBALANCE_TEMPERATURE;Tenperatura !HISTORY_MSG_LOCALCONTRAST_RADIUS;Local Contrast - Radius !HISTORY_MSG_METADATA_MODE;Metadata copy mode !HISTORY_MSG_MICROCONTRAST_CONTRAST;Microcontrast - Contrast threshold +!HISTORY_MSG_PIXELSHIFT_DEMOSAIC;PS - Demosaic method for motion !HISTORY_MSG_PREPROCESS_LINEDENOISE_DIRECTION;Line noise filter direction !HISTORY_MSG_PREPROCESS_PDAFLINESFILTER;PDAF lines filter !HISTORY_MSG_PRSHARPEN_CONTRAST;PRS - Contrast threshold @@ -1813,14 +1815,17 @@ TP_WBALANCE_TEMPERATURE;Tenperatura !TP_RAWEXPOS_TWOGREEN;Link greens !TP_RAW_1PASSMEDIUM;1-Pass (Medium) !TP_RAW_3PASSBEST;3-Pass (Best) +!TP_RAW_4PASS;4-Pass !TP_RAW_AHD;AHD !TP_RAW_AMAZE;AMaZE +!TP_RAW_AMAZEVNG4;AMaZE+VNG4 !TP_RAW_DCB;DCB !TP_RAW_DCBENHANCE;DCB enhancement !TP_RAW_DCBITERATIONS;Number of DCB iterations !TP_RAW_DMETHOD_PROGRESSBAR;%1 demosaicing... !TP_RAW_DMETHOD_PROGRESSBAR_REFINE;Demosaicing refinement... !TP_RAW_DMETHOD_TOOLTIP;Note: IGV and LMMSE are dedicated to high ISO images to aid in noise reduction without leading to maze patterns, posterization or a washed-out look.\nPixel Shift is for Pentax/Sony Pixel Shift files. It falls back to AMaZE for non-Pixel Shift files. +!TP_RAW_DUALDEMOSAICCONTRAST;Contrast threshold !TP_RAW_EAHD;EAHD !TP_RAW_FAST;Fast !TP_RAW_HD;Threshold @@ -1837,6 +1842,7 @@ TP_WBALANCE_TEMPERATURE;Tenperatura !TP_RAW_NONE;None (Shows sensor pattern) !TP_RAW_PIXELSHIFT;Pixel Shift !TP_RAW_PIXELSHIFTBLUR;Blur motion mask +!TP_RAW_PIXELSHIFTDMETHOD;Demosaic method for motion !TP_RAW_PIXELSHIFTEPERISO;Sensitivity !TP_RAW_PIXELSHIFTEPERISO_TOOLTIP;The default value of 0 should work fine for base ISO.\nHigher values increase sensitivity of motion detection.\nChange in small steps and watch the motion mask while changing.\nIncrease sensitivity for underexposed or high ISO images. !TP_RAW_PIXELSHIFTEQUALBRIGHT;Equalize brightness of frames diff --git a/rtdata/languages/Greek b/rtdata/languages/Greek index 15d2dcc60..8d9cd5815 100644 --- a/rtdata/languages/Greek +++ b/rtdata/languages/Greek @@ -978,6 +978,7 @@ TP_WBALANCE_TEMPERATURE;Θερμοκρασία !HISTORY_MSG_493;L*a*b* Adjustments !HISTORY_MSG_CLAMPOOG;Out-of-gamut color clipping !HISTORY_MSG_COLORTONING_LABGRID_VALUE;CT - Color correction +!HISTORY_MSG_DUALDEMOSAIC_CONTRAST;AMaZE+VNG4 - Contrast threshold !HISTORY_MSG_HISTMATCHING;Auto-Matched Tone Curve !HISTORY_MSG_LOCALCONTRAST_AMOUNT;Local Contrast - Amount !HISTORY_MSG_LOCALCONTRAST_DARKNESS;Local Contrast - Darkness @@ -986,6 +987,7 @@ TP_WBALANCE_TEMPERATURE;Θερμοκρασία !HISTORY_MSG_LOCALCONTRAST_RADIUS;Local Contrast - Radius !HISTORY_MSG_METADATA_MODE;Metadata copy mode !HISTORY_MSG_MICROCONTRAST_CONTRAST;Microcontrast - Contrast threshold +!HISTORY_MSG_PIXELSHIFT_DEMOSAIC;PS - Demosaic method for motion !HISTORY_MSG_PREPROCESS_LINEDENOISE_DIRECTION;Line noise filter direction !HISTORY_MSG_PREPROCESS_PDAFLINESFILTER;PDAF lines filter !HISTORY_MSG_PRSHARPEN_CONTRAST;PRS - Contrast threshold @@ -1812,14 +1814,17 @@ TP_WBALANCE_TEMPERATURE;Θερμοκρασία !TP_RAWEXPOS_TWOGREEN;Link greens !TP_RAW_1PASSMEDIUM;1-Pass (Medium) !TP_RAW_3PASSBEST;3-Pass (Best) +!TP_RAW_4PASS;4-Pass !TP_RAW_AHD;AHD !TP_RAW_AMAZE;AMaZE +!TP_RAW_AMAZEVNG4;AMaZE+VNG4 !TP_RAW_DCB;DCB !TP_RAW_DCBENHANCE;DCB enhancement !TP_RAW_DCBITERATIONS;Number of DCB iterations !TP_RAW_DMETHOD_PROGRESSBAR;%1 demosaicing... !TP_RAW_DMETHOD_PROGRESSBAR_REFINE;Demosaicing refinement... !TP_RAW_DMETHOD_TOOLTIP;Note: IGV and LMMSE are dedicated to high ISO images to aid in noise reduction without leading to maze patterns, posterization or a washed-out look.\nPixel Shift is for Pentax/Sony Pixel Shift files. It falls back to AMaZE for non-Pixel Shift files. +!TP_RAW_DUALDEMOSAICCONTRAST;Contrast threshold !TP_RAW_EAHD;EAHD !TP_RAW_FAST;Fast !TP_RAW_HD;Threshold @@ -1836,6 +1841,7 @@ TP_WBALANCE_TEMPERATURE;Θερμοκρασία !TP_RAW_NONE;None (Shows sensor pattern) !TP_RAW_PIXELSHIFT;Pixel Shift !TP_RAW_PIXELSHIFTBLUR;Blur motion mask +!TP_RAW_PIXELSHIFTDMETHOD;Demosaic method for motion !TP_RAW_PIXELSHIFTEPERISO;Sensitivity !TP_RAW_PIXELSHIFTEPERISO_TOOLTIP;The default value of 0 should work fine for base ISO.\nHigher values increase sensitivity of motion detection.\nChange in small steps and watch the motion mask while changing.\nIncrease sensitivity for underexposed or high ISO images. !TP_RAW_PIXELSHIFTEQUALBRIGHT;Equalize brightness of frames diff --git a/rtdata/languages/Hebrew b/rtdata/languages/Hebrew index 8eed4426e..223d2e45c 100644 --- a/rtdata/languages/Hebrew +++ b/rtdata/languages/Hebrew @@ -979,6 +979,7 @@ TP_WBALANCE_TEMPERATURE;מידת חום !HISTORY_MSG_493;L*a*b* Adjustments !HISTORY_MSG_CLAMPOOG;Out-of-gamut color clipping !HISTORY_MSG_COLORTONING_LABGRID_VALUE;CT - Color correction +!HISTORY_MSG_DUALDEMOSAIC_CONTRAST;AMaZE+VNG4 - Contrast threshold !HISTORY_MSG_HISTMATCHING;Auto-Matched Tone Curve !HISTORY_MSG_LOCALCONTRAST_AMOUNT;Local Contrast - Amount !HISTORY_MSG_LOCALCONTRAST_DARKNESS;Local Contrast - Darkness @@ -987,6 +988,7 @@ TP_WBALANCE_TEMPERATURE;מידת חום !HISTORY_MSG_LOCALCONTRAST_RADIUS;Local Contrast - Radius !HISTORY_MSG_METADATA_MODE;Metadata copy mode !HISTORY_MSG_MICROCONTRAST_CONTRAST;Microcontrast - Contrast threshold +!HISTORY_MSG_PIXELSHIFT_DEMOSAIC;PS - Demosaic method for motion !HISTORY_MSG_PREPROCESS_LINEDENOISE_DIRECTION;Line noise filter direction !HISTORY_MSG_PREPROCESS_PDAFLINESFILTER;PDAF lines filter !HISTORY_MSG_PRSHARPEN_CONTRAST;PRS - Contrast threshold @@ -1813,14 +1815,17 @@ TP_WBALANCE_TEMPERATURE;מידת חום !TP_RAWEXPOS_TWOGREEN;Link greens !TP_RAW_1PASSMEDIUM;1-Pass (Medium) !TP_RAW_3PASSBEST;3-Pass (Best) +!TP_RAW_4PASS;4-Pass !TP_RAW_AHD;AHD !TP_RAW_AMAZE;AMaZE +!TP_RAW_AMAZEVNG4;AMaZE+VNG4 !TP_RAW_DCB;DCB !TP_RAW_DCBENHANCE;DCB enhancement !TP_RAW_DCBITERATIONS;Number of DCB iterations !TP_RAW_DMETHOD_PROGRESSBAR;%1 demosaicing... !TP_RAW_DMETHOD_PROGRESSBAR_REFINE;Demosaicing refinement... !TP_RAW_DMETHOD_TOOLTIP;Note: IGV and LMMSE are dedicated to high ISO images to aid in noise reduction without leading to maze patterns, posterization or a washed-out look.\nPixel Shift is for Pentax/Sony Pixel Shift files. It falls back to AMaZE for non-Pixel Shift files. +!TP_RAW_DUALDEMOSAICCONTRAST;Contrast threshold !TP_RAW_EAHD;EAHD !TP_RAW_FAST;Fast !TP_RAW_HD;Threshold @@ -1837,6 +1842,7 @@ TP_WBALANCE_TEMPERATURE;מידת חום !TP_RAW_NONE;None (Shows sensor pattern) !TP_RAW_PIXELSHIFT;Pixel Shift !TP_RAW_PIXELSHIFTBLUR;Blur motion mask +!TP_RAW_PIXELSHIFTDMETHOD;Demosaic method for motion !TP_RAW_PIXELSHIFTEPERISO;Sensitivity !TP_RAW_PIXELSHIFTEPERISO_TOOLTIP;The default value of 0 should work fine for base ISO.\nHigher values increase sensitivity of motion detection.\nChange in small steps and watch the motion mask while changing.\nIncrease sensitivity for underexposed or high ISO images. !TP_RAW_PIXELSHIFTEQUALBRIGHT;Equalize brightness of frames diff --git a/rtdata/languages/Italiano b/rtdata/languages/Italiano index 898bfb188..9a7db12e9 100644 --- a/rtdata/languages/Italiano +++ b/rtdata/languages/Italiano @@ -1583,6 +1583,7 @@ ZOOMPANEL_ZOOMOUT;Rimpicciolisci.\nScorciatoia: - !HISTORY_MSG_493;L*a*b* Adjustments !HISTORY_MSG_CLAMPOOG;Out-of-gamut color clipping !HISTORY_MSG_COLORTONING_LABGRID_VALUE;CT - Color correction +!HISTORY_MSG_DUALDEMOSAIC_CONTRAST;AMaZE+VNG4 - Contrast threshold !HISTORY_MSG_HISTMATCHING;Auto-Matched Tone Curve !HISTORY_MSG_LOCALCONTRAST_AMOUNT;Local Contrast - Amount !HISTORY_MSG_LOCALCONTRAST_DARKNESS;Local Contrast - Darkness @@ -1591,6 +1592,7 @@ ZOOMPANEL_ZOOMOUT;Rimpicciolisci.\nScorciatoia: - !HISTORY_MSG_LOCALCONTRAST_RADIUS;Local Contrast - Radius !HISTORY_MSG_METADATA_MODE;Metadata copy mode !HISTORY_MSG_MICROCONTRAST_CONTRAST;Microcontrast - Contrast threshold +!HISTORY_MSG_PIXELSHIFT_DEMOSAIC;PS - Demosaic method for motion !HISTORY_MSG_PREPROCESS_LINEDENOISE_DIRECTION;Line noise filter direction !HISTORY_MSG_PREPROCESS_PDAFLINESFILTER;PDAF lines filter !HISTORY_MSG_PRSHARPEN_CONTRAST;PRS - Contrast threshold @@ -1915,9 +1917,12 @@ ZOOMPANEL_ZOOMOUT;Rimpicciolisci.\nScorciatoia: - !TP_RAWEXPOS_RGB;Red, Green, Blue !TP_RAW_1PASSMEDIUM;1-Pass (Medium) !TP_RAW_3PASSBEST;3-Pass (Best) +!TP_RAW_4PASS;4-Pass !TP_RAW_AHD;AHD !TP_RAW_AMAZE;AMaZE +!TP_RAW_AMAZEVNG4;AMaZE+VNG4 !TP_RAW_DCB;DCB +!TP_RAW_DUALDEMOSAICCONTRAST;Contrast threshold !TP_RAW_EAHD;EAHD !TP_RAW_FAST;Fast !TP_RAW_HD;Threshold @@ -1931,6 +1936,7 @@ ZOOMPANEL_ZOOMOUT;Rimpicciolisci.\nScorciatoia: - !TP_RAW_NONE;None (Shows sensor pattern) !TP_RAW_PIXELSHIFT;Pixel Shift !TP_RAW_PIXELSHIFTBLUR;Blur motion mask +!TP_RAW_PIXELSHIFTDMETHOD;Demosaic method for motion !TP_RAW_PIXELSHIFTEPERISO;Sensitivity !TP_RAW_PIXELSHIFTEPERISO_TOOLTIP;The default value of 0 should work fine for base ISO.\nHigher values increase sensitivity of motion detection.\nChange in small steps and watch the motion mask while changing.\nIncrease sensitivity for underexposed or high ISO images. !TP_RAW_PIXELSHIFTEQUALBRIGHT;Equalize brightness of frames diff --git a/rtdata/languages/Latvian b/rtdata/languages/Latvian index 6f3d76156..d951d2461 100644 --- a/rtdata/languages/Latvian +++ b/rtdata/languages/Latvian @@ -979,6 +979,7 @@ TP_WBALANCE_TEMPERATURE;Temperatūra !HISTORY_MSG_493;L*a*b* Adjustments !HISTORY_MSG_CLAMPOOG;Out-of-gamut color clipping !HISTORY_MSG_COLORTONING_LABGRID_VALUE;CT - Color correction +!HISTORY_MSG_DUALDEMOSAIC_CONTRAST;AMaZE+VNG4 - Contrast threshold !HISTORY_MSG_HISTMATCHING;Auto-Matched Tone Curve !HISTORY_MSG_LOCALCONTRAST_AMOUNT;Local Contrast - Amount !HISTORY_MSG_LOCALCONTRAST_DARKNESS;Local Contrast - Darkness @@ -987,6 +988,7 @@ TP_WBALANCE_TEMPERATURE;Temperatūra !HISTORY_MSG_LOCALCONTRAST_RADIUS;Local Contrast - Radius !HISTORY_MSG_METADATA_MODE;Metadata copy mode !HISTORY_MSG_MICROCONTRAST_CONTRAST;Microcontrast - Contrast threshold +!HISTORY_MSG_PIXELSHIFT_DEMOSAIC;PS - Demosaic method for motion !HISTORY_MSG_PREPROCESS_LINEDENOISE_DIRECTION;Line noise filter direction !HISTORY_MSG_PREPROCESS_PDAFLINESFILTER;PDAF lines filter !HISTORY_MSG_PRSHARPEN_CONTRAST;PRS - Contrast threshold @@ -1813,14 +1815,17 @@ TP_WBALANCE_TEMPERATURE;Temperatūra !TP_RAWEXPOS_TWOGREEN;Link greens !TP_RAW_1PASSMEDIUM;1-Pass (Medium) !TP_RAW_3PASSBEST;3-Pass (Best) +!TP_RAW_4PASS;4-Pass !TP_RAW_AHD;AHD !TP_RAW_AMAZE;AMaZE +!TP_RAW_AMAZEVNG4;AMaZE+VNG4 !TP_RAW_DCB;DCB !TP_RAW_DCBENHANCE;DCB enhancement !TP_RAW_DCBITERATIONS;Number of DCB iterations !TP_RAW_DMETHOD_PROGRESSBAR;%1 demosaicing... !TP_RAW_DMETHOD_PROGRESSBAR_REFINE;Demosaicing refinement... !TP_RAW_DMETHOD_TOOLTIP;Note: IGV and LMMSE are dedicated to high ISO images to aid in noise reduction without leading to maze patterns, posterization or a washed-out look.\nPixel Shift is for Pentax/Sony Pixel Shift files. It falls back to AMaZE for non-Pixel Shift files. +!TP_RAW_DUALDEMOSAICCONTRAST;Contrast threshold !TP_RAW_EAHD;EAHD !TP_RAW_FAST;Fast !TP_RAW_HD;Threshold @@ -1837,6 +1842,7 @@ TP_WBALANCE_TEMPERATURE;Temperatūra !TP_RAW_NONE;None (Shows sensor pattern) !TP_RAW_PIXELSHIFT;Pixel Shift !TP_RAW_PIXELSHIFTBLUR;Blur motion mask +!TP_RAW_PIXELSHIFTDMETHOD;Demosaic method for motion !TP_RAW_PIXELSHIFTEPERISO;Sensitivity !TP_RAW_PIXELSHIFTEPERISO_TOOLTIP;The default value of 0 should work fine for base ISO.\nHigher values increase sensitivity of motion detection.\nChange in small steps and watch the motion mask while changing.\nIncrease sensitivity for underexposed or high ISO images. !TP_RAW_PIXELSHIFTEQUALBRIGHT;Equalize brightness of frames diff --git a/rtdata/languages/Magyar b/rtdata/languages/Magyar index 6d8e29d59..70489ded5 100644 --- a/rtdata/languages/Magyar +++ b/rtdata/languages/Magyar @@ -1252,6 +1252,7 @@ ZOOMPANEL_ZOOMOUT;Kicsinyítés - !HISTORY_MSG_493;L*a*b* Adjustments !HISTORY_MSG_CLAMPOOG;Out-of-gamut color clipping !HISTORY_MSG_COLORTONING_LABGRID_VALUE;CT - Color correction +!HISTORY_MSG_DUALDEMOSAIC_CONTRAST;AMaZE+VNG4 - Contrast threshold !HISTORY_MSG_HISTMATCHING;Auto-Matched Tone Curve !HISTORY_MSG_LOCALCONTRAST_AMOUNT;Local Contrast - Amount !HISTORY_MSG_LOCALCONTRAST_DARKNESS;Local Contrast - Darkness @@ -1260,6 +1261,7 @@ ZOOMPANEL_ZOOMOUT;Kicsinyítés - !HISTORY_MSG_LOCALCONTRAST_RADIUS;Local Contrast - Radius !HISTORY_MSG_METADATA_MODE;Metadata copy mode !HISTORY_MSG_MICROCONTRAST_CONTRAST;Microcontrast - Contrast threshold +!HISTORY_MSG_PIXELSHIFT_DEMOSAIC;PS - Demosaic method for motion !HISTORY_MSG_PREPROCESS_LINEDENOISE_DIRECTION;Line noise filter direction !HISTORY_MSG_PREPROCESS_PDAFLINESFILTER;PDAF lines filter !HISTORY_MSG_PRSHARPEN_CONTRAST;PRS - Contrast threshold @@ -1887,12 +1889,15 @@ ZOOMPANEL_ZOOMOUT;Kicsinyítés - !TP_RAWEXPOS_RGB;Red, Green, Blue !TP_RAW_1PASSMEDIUM;1-Pass (Medium) !TP_RAW_3PASSBEST;3-Pass (Best) +!TP_RAW_4PASS;4-Pass !TP_RAW_AHD;AHD !TP_RAW_AMAZE;AMaZE +!TP_RAW_AMAZEVNG4;AMaZE+VNG4 !TP_RAW_DCB;DCB !TP_RAW_DMETHOD_PROGRESSBAR;%1 demosaicing... !TP_RAW_DMETHOD_PROGRESSBAR_REFINE;Demosaicing refinement... !TP_RAW_DMETHOD_TOOLTIP;Note: IGV and LMMSE are dedicated to high ISO images to aid in noise reduction without leading to maze patterns, posterization or a washed-out look.\nPixel Shift is for Pentax/Sony Pixel Shift files. It falls back to AMaZE for non-Pixel Shift files. +!TP_RAW_DUALDEMOSAICCONTRAST;Contrast threshold !TP_RAW_EAHD;EAHD !TP_RAW_FAST;Fast !TP_RAW_HD;Threshold @@ -1908,6 +1913,7 @@ ZOOMPANEL_ZOOMOUT;Kicsinyítés - !TP_RAW_NONE;None (Shows sensor pattern) !TP_RAW_PIXELSHIFT;Pixel Shift !TP_RAW_PIXELSHIFTBLUR;Blur motion mask +!TP_RAW_PIXELSHIFTDMETHOD;Demosaic method for motion !TP_RAW_PIXELSHIFTEPERISO;Sensitivity !TP_RAW_PIXELSHIFTEPERISO_TOOLTIP;The default value of 0 should work fine for base ISO.\nHigher values increase sensitivity of motion detection.\nChange in small steps and watch the motion mask while changing.\nIncrease sensitivity for underexposed or high ISO images. !TP_RAW_PIXELSHIFTEQUALBRIGHT;Equalize brightness of frames diff --git a/rtdata/languages/Nederlands b/rtdata/languages/Nederlands index 35d07dcef..aa96073a4 100644 --- a/rtdata/languages/Nederlands +++ b/rtdata/languages/Nederlands @@ -2143,6 +2143,7 @@ ZOOMPANEL_ZOOMOUT;Zoom uit\nSneltoets: - !HISTORY_MSG_493;L*a*b* Adjustments !HISTORY_MSG_CLAMPOOG;Out-of-gamut color clipping !HISTORY_MSG_COLORTONING_LABGRID_VALUE;CT - Color correction +!HISTORY_MSG_DUALDEMOSAIC_CONTRAST;AMaZE+VNG4 - Contrast threshold !HISTORY_MSG_HISTMATCHING;Auto-Matched Tone Curve !HISTORY_MSG_LOCALCONTRAST_AMOUNT;Local Contrast - Amount !HISTORY_MSG_LOCALCONTRAST_DARKNESS;Local Contrast - Darkness @@ -2151,6 +2152,7 @@ ZOOMPANEL_ZOOMOUT;Zoom uit\nSneltoets: - !HISTORY_MSG_LOCALCONTRAST_RADIUS;Local Contrast - Radius !HISTORY_MSG_METADATA_MODE;Metadata copy mode !HISTORY_MSG_MICROCONTRAST_CONTRAST;Microcontrast - Contrast threshold +!HISTORY_MSG_PIXELSHIFT_DEMOSAIC;PS - Demosaic method for motion !HISTORY_MSG_PREPROCESS_LINEDENOISE_DIRECTION;Line noise filter direction !HISTORY_MSG_PREPROCESS_PDAFLINESFILTER;PDAF lines filter !HISTORY_MSG_PRSHARPEN_CONTRAST;PRS - Contrast threshold @@ -2236,7 +2238,11 @@ ZOOMPANEL_ZOOMOUT;Zoom uit\nSneltoets: - !TP_PREPROCESS_LINEDENOISE_DIRECTION_VERTICAL;Vertical !TP_PREPROCESS_PDAFLINESFILTER;PDAF lines filter !TP_PREPROCESS_PDAFLINESFILTER_TOOLTIP;Tries to suppress stripe noise caused by on-sensor PDAF pixels, occurring with some Sony mirrorless cameras on some backlit scenes with visible flare. +!TP_RAW_4PASS;4-Pass +!TP_RAW_AMAZEVNG4;AMaZE+VNG4 +!TP_RAW_DUALDEMOSAICCONTRAST;Contrast threshold !TP_RAW_IMAGENUM_TOOLTIP;Some raw files consist of several sub-images (Pentax/Sony Pixel Shift, Pentax 3-in-1 HDR, Canon Dual Pixel).\n\nWhen using any demosaicing method other than Pixel Shift, this selects which sub-image is used.\n\nWhen using the Pixel Shift demosaicing method on a Pixel Shift raw, all sub-images are used, and this selects which sub-image should be used for moving parts. +!TP_RAW_PIXELSHIFTDMETHOD;Demosaic method for motion !TP_RAW_PIXELSHIFTEPERISO;Sensitivity !TP_RAW_PIXELSHIFTEPERISO_TOOLTIP;The default value of 0 should work fine for base ISO.\nHigher values increase sensitivity of motion detection.\nChange in small steps and watch the motion mask while changing.\nIncrease sensitivity for underexposed or high ISO images. !TP_RAW_PIXELSHIFTEQUALBRIGHTCHANNEL;Equalize per channel diff --git a/rtdata/languages/Norsk BM b/rtdata/languages/Norsk BM index db3a3b569..b433dc902 100644 --- a/rtdata/languages/Norsk BM +++ b/rtdata/languages/Norsk BM @@ -978,6 +978,7 @@ TP_WBALANCE_TEMPERATURE;Temperatur !HISTORY_MSG_493;L*a*b* Adjustments !HISTORY_MSG_CLAMPOOG;Out-of-gamut color clipping !HISTORY_MSG_COLORTONING_LABGRID_VALUE;CT - Color correction +!HISTORY_MSG_DUALDEMOSAIC_CONTRAST;AMaZE+VNG4 - Contrast threshold !HISTORY_MSG_HISTMATCHING;Auto-Matched Tone Curve !HISTORY_MSG_LOCALCONTRAST_AMOUNT;Local Contrast - Amount !HISTORY_MSG_LOCALCONTRAST_DARKNESS;Local Contrast - Darkness @@ -986,6 +987,7 @@ TP_WBALANCE_TEMPERATURE;Temperatur !HISTORY_MSG_LOCALCONTRAST_RADIUS;Local Contrast - Radius !HISTORY_MSG_METADATA_MODE;Metadata copy mode !HISTORY_MSG_MICROCONTRAST_CONTRAST;Microcontrast - Contrast threshold +!HISTORY_MSG_PIXELSHIFT_DEMOSAIC;PS - Demosaic method for motion !HISTORY_MSG_PREPROCESS_LINEDENOISE_DIRECTION;Line noise filter direction !HISTORY_MSG_PREPROCESS_PDAFLINESFILTER;PDAF lines filter !HISTORY_MSG_PRSHARPEN_CONTRAST;PRS - Contrast threshold @@ -1812,14 +1814,17 @@ TP_WBALANCE_TEMPERATURE;Temperatur !TP_RAWEXPOS_TWOGREEN;Link greens !TP_RAW_1PASSMEDIUM;1-Pass (Medium) !TP_RAW_3PASSBEST;3-Pass (Best) +!TP_RAW_4PASS;4-Pass !TP_RAW_AHD;AHD !TP_RAW_AMAZE;AMaZE +!TP_RAW_AMAZEVNG4;AMaZE+VNG4 !TP_RAW_DCB;DCB !TP_RAW_DCBENHANCE;DCB enhancement !TP_RAW_DCBITERATIONS;Number of DCB iterations !TP_RAW_DMETHOD_PROGRESSBAR;%1 demosaicing... !TP_RAW_DMETHOD_PROGRESSBAR_REFINE;Demosaicing refinement... !TP_RAW_DMETHOD_TOOLTIP;Note: IGV and LMMSE are dedicated to high ISO images to aid in noise reduction without leading to maze patterns, posterization or a washed-out look.\nPixel Shift is for Pentax/Sony Pixel Shift files. It falls back to AMaZE for non-Pixel Shift files. +!TP_RAW_DUALDEMOSAICCONTRAST;Contrast threshold !TP_RAW_EAHD;EAHD !TP_RAW_FAST;Fast !TP_RAW_HD;Threshold @@ -1836,6 +1841,7 @@ TP_WBALANCE_TEMPERATURE;Temperatur !TP_RAW_NONE;None (Shows sensor pattern) !TP_RAW_PIXELSHIFT;Pixel Shift !TP_RAW_PIXELSHIFTBLUR;Blur motion mask +!TP_RAW_PIXELSHIFTDMETHOD;Demosaic method for motion !TP_RAW_PIXELSHIFTEPERISO;Sensitivity !TP_RAW_PIXELSHIFTEPERISO_TOOLTIP;The default value of 0 should work fine for base ISO.\nHigher values increase sensitivity of motion detection.\nChange in small steps and watch the motion mask while changing.\nIncrease sensitivity for underexposed or high ISO images. !TP_RAW_PIXELSHIFTEQUALBRIGHT;Equalize brightness of frames diff --git a/rtdata/languages/Polish b/rtdata/languages/Polish index 021c3b1e8..b9b336f3f 100644 --- a/rtdata/languages/Polish +++ b/rtdata/languages/Polish @@ -1665,6 +1665,7 @@ ZOOMPANEL_ZOOMOUT;Oddal\nSkrót: - !HISTORY_MSG_493;L*a*b* Adjustments !HISTORY_MSG_CLAMPOOG;Out-of-gamut color clipping !HISTORY_MSG_COLORTONING_LABGRID_VALUE;CT - Color correction +!HISTORY_MSG_DUALDEMOSAIC_CONTRAST;AMaZE+VNG4 - Contrast threshold !HISTORY_MSG_HISTMATCHING;Auto-Matched Tone Curve !HISTORY_MSG_LOCALCONTRAST_AMOUNT;Local Contrast - Amount !HISTORY_MSG_LOCALCONTRAST_DARKNESS;Local Contrast - Darkness @@ -1673,6 +1674,7 @@ ZOOMPANEL_ZOOMOUT;Oddal\nSkrót: - !HISTORY_MSG_LOCALCONTRAST_RADIUS;Local Contrast - Radius !HISTORY_MSG_METADATA_MODE;Metadata copy mode !HISTORY_MSG_MICROCONTRAST_CONTRAST;Microcontrast - Contrast threshold +!HISTORY_MSG_PIXELSHIFT_DEMOSAIC;PS - Demosaic method for motion !HISTORY_MSG_PREPROCESS_LINEDENOISE_DIRECTION;Line noise filter direction !HISTORY_MSG_PREPROCESS_PDAFLINESFILTER;PDAF lines filter !HISTORY_MSG_PRSHARPEN_CONTRAST;PRS - Contrast threshold @@ -1924,9 +1926,12 @@ ZOOMPANEL_ZOOMOUT;Oddal\nSkrót: - !TP_RAWCACORR_CASTR;Strength !TP_RAW_1PASSMEDIUM;1-Pass (Medium) !TP_RAW_3PASSBEST;3-Pass (Best) +!TP_RAW_4PASS;4-Pass !TP_RAW_AHD;AHD !TP_RAW_AMAZE;AMaZE +!TP_RAW_AMAZEVNG4;AMaZE+VNG4 !TP_RAW_DCB;DCB +!TP_RAW_DUALDEMOSAICCONTRAST;Contrast threshold !TP_RAW_EAHD;EAHD !TP_RAW_FAST;Fast !TP_RAW_HD;Threshold @@ -1940,6 +1945,7 @@ ZOOMPANEL_ZOOMOUT;Oddal\nSkrót: - !TP_RAW_NONE;None (Shows sensor pattern) !TP_RAW_PIXELSHIFT;Pixel Shift !TP_RAW_PIXELSHIFTBLUR;Blur motion mask +!TP_RAW_PIXELSHIFTDMETHOD;Demosaic method for motion !TP_RAW_PIXELSHIFTEPERISO;Sensitivity !TP_RAW_PIXELSHIFTEPERISO_TOOLTIP;The default value of 0 should work fine for base ISO.\nHigher values increase sensitivity of motion detection.\nChange in small steps and watch the motion mask while changing.\nIncrease sensitivity for underexposed or high ISO images. !TP_RAW_PIXELSHIFTEQUALBRIGHT;Equalize brightness of frames diff --git a/rtdata/languages/Polish (Latin Characters) b/rtdata/languages/Polish (Latin Characters) index f34fb4791..19ca6a4dd 100644 --- a/rtdata/languages/Polish (Latin Characters) +++ b/rtdata/languages/Polish (Latin Characters) @@ -1665,6 +1665,7 @@ ZOOMPANEL_ZOOMOUT;Oddal\nSkrot: - !HISTORY_MSG_493;L*a*b* Adjustments !HISTORY_MSG_CLAMPOOG;Out-of-gamut color clipping !HISTORY_MSG_COLORTONING_LABGRID_VALUE;CT - Color correction +!HISTORY_MSG_DUALDEMOSAIC_CONTRAST;AMaZE+VNG4 - Contrast threshold !HISTORY_MSG_HISTMATCHING;Auto-Matched Tone Curve !HISTORY_MSG_LOCALCONTRAST_AMOUNT;Local Contrast - Amount !HISTORY_MSG_LOCALCONTRAST_DARKNESS;Local Contrast - Darkness @@ -1673,6 +1674,7 @@ ZOOMPANEL_ZOOMOUT;Oddal\nSkrot: - !HISTORY_MSG_LOCALCONTRAST_RADIUS;Local Contrast - Radius !HISTORY_MSG_METADATA_MODE;Metadata copy mode !HISTORY_MSG_MICROCONTRAST_CONTRAST;Microcontrast - Contrast threshold +!HISTORY_MSG_PIXELSHIFT_DEMOSAIC;PS - Demosaic method for motion !HISTORY_MSG_PREPROCESS_LINEDENOISE_DIRECTION;Line noise filter direction !HISTORY_MSG_PREPROCESS_PDAFLINESFILTER;PDAF lines filter !HISTORY_MSG_PRSHARPEN_CONTRAST;PRS - Contrast threshold @@ -1924,9 +1926,12 @@ ZOOMPANEL_ZOOMOUT;Oddal\nSkrot: - !TP_RAWCACORR_CASTR;Strength !TP_RAW_1PASSMEDIUM;1-Pass (Medium) !TP_RAW_3PASSBEST;3-Pass (Best) +!TP_RAW_4PASS;4-Pass !TP_RAW_AHD;AHD !TP_RAW_AMAZE;AMaZE +!TP_RAW_AMAZEVNG4;AMaZE+VNG4 !TP_RAW_DCB;DCB +!TP_RAW_DUALDEMOSAICCONTRAST;Contrast threshold !TP_RAW_EAHD;EAHD !TP_RAW_FAST;Fast !TP_RAW_HD;Threshold @@ -1940,6 +1945,7 @@ ZOOMPANEL_ZOOMOUT;Oddal\nSkrot: - !TP_RAW_NONE;None (Shows sensor pattern) !TP_RAW_PIXELSHIFT;Pixel Shift !TP_RAW_PIXELSHIFTBLUR;Blur motion mask +!TP_RAW_PIXELSHIFTDMETHOD;Demosaic method for motion !TP_RAW_PIXELSHIFTEPERISO;Sensitivity !TP_RAW_PIXELSHIFTEPERISO_TOOLTIP;The default value of 0 should work fine for base ISO.\nHigher values increase sensitivity of motion detection.\nChange in small steps and watch the motion mask while changing.\nIncrease sensitivity for underexposed or high ISO images. !TP_RAW_PIXELSHIFTEQUALBRIGHT;Equalize brightness of frames diff --git a/rtdata/languages/Portugues (Brasil) b/rtdata/languages/Portugues (Brasil) index 6fa8881a4..961b18455 100644 --- a/rtdata/languages/Portugues (Brasil) +++ b/rtdata/languages/Portugues (Brasil) @@ -1633,7 +1633,9 @@ TP_ICM_DCPILLUMINANT_INTERPOLATED;Interpolado !HISTORY_MSG_488;Dynamic Range Compression !HISTORY_MSG_489;DRC - Threshold !HISTORY_MSG_490;DRC - Amount +!HISTORY_MSG_DUALDEMOSAIC_CONTRAST;AMaZE+VNG4 - Contrast threshold !HISTORY_MSG_MICROCONTRAST_CONTRAST;Microcontrast - Contrast threshold +!HISTORY_MSG_PIXELSHIFT_DEMOSAIC;PS - Demosaic method for motion !HISTORY_MSG_PRSHARPEN_CONTRAST;PRS - Contrast threshold !HISTORY_MSG_SHARPENING_CONTRAST;Sharpening - Contrast threshold !HISTORY_MSG_TM_FATTAL_ANCHOR;DRC - Anchor @@ -1766,8 +1768,10 @@ TP_ICM_DCPILLUMINANT_INTERPOLATED;Interpolado !TP_RAWEXPOS_TWOGREEN;Link greens !TP_RAW_1PASSMEDIUM;1-Pass (Medium) !TP_RAW_3PASSBEST;3-Pass (Best) +!TP_RAW_4PASS;4-Pass !TP_RAW_AHD;AHD !TP_RAW_AMAZE;AMaZE +!TP_RAW_AMAZEVNG4;AMaZE+VNG4 !TP_RAW_DCB;DCB !TP_RAW_DCBENHANCE;DCB enhancement !TP_RAW_DCBITERATIONS;Number of DCB iterations @@ -1775,6 +1779,7 @@ TP_ICM_DCPILLUMINANT_INTERPOLATED;Interpolado !TP_RAW_DMETHOD_PROGRESSBAR;%1 demosaicing... !TP_RAW_DMETHOD_PROGRESSBAR_REFINE;Demosaicing refinement... !TP_RAW_DMETHOD_TOOLTIP;Note: IGV and LMMSE are dedicated to high ISO images to aid in noise reduction without leading to maze patterns, posterization or a washed-out look.\nPixel Shift is for Pentax/Sony Pixel Shift files. It falls back to AMaZE for non-Pixel Shift files. +!TP_RAW_DUALDEMOSAICCONTRAST;Contrast threshold !TP_RAW_EAHD;EAHD !TP_RAW_FALSECOLOR;False color suppression steps !TP_RAW_FAST;Fast @@ -1792,6 +1797,7 @@ TP_ICM_DCPILLUMINANT_INTERPOLATED;Interpolado !TP_RAW_NONE;None (Shows sensor pattern) !TP_RAW_PIXELSHIFT;Pixel Shift !TP_RAW_PIXELSHIFTBLUR;Blur motion mask +!TP_RAW_PIXELSHIFTDMETHOD;Demosaic method for motion !TP_RAW_PIXELSHIFTEPERISO;Sensitivity !TP_RAW_PIXELSHIFTEPERISO_TOOLTIP;The default value of 0 should work fine for base ISO.\nHigher values increase sensitivity of motion detection.\nChange in small steps and watch the motion mask while changing.\nIncrease sensitivity for underexposed or high ISO images. !TP_RAW_PIXELSHIFTEQUALBRIGHT;Equalize brightness of frames diff --git a/rtdata/languages/Russian b/rtdata/languages/Russian index 6ca6b1066..089381e47 100644 --- a/rtdata/languages/Russian +++ b/rtdata/languages/Russian @@ -1645,7 +1645,9 @@ ZOOMPANEL_ZOOMOUT;Отдалить\nГорячая клавиша: - !HISTORY_MSG_490;DRC - Amount !HISTORY_MSG_CLAMPOOG;Out-of-gamut color clipping !HISTORY_MSG_COLORTONING_LABGRID_VALUE;CT - Color correction +!HISTORY_MSG_DUALDEMOSAIC_CONTRAST;AMaZE+VNG4 - Contrast threshold !HISTORY_MSG_MICROCONTRAST_CONTRAST;Microcontrast - Contrast threshold +!HISTORY_MSG_PIXELSHIFT_DEMOSAIC;PS - Demosaic method for motion !HISTORY_MSG_PREPROCESS_LINEDENOISE_DIRECTION;Line noise filter direction !HISTORY_MSG_PREPROCESS_PDAFLINESFILTER;PDAF lines filter !HISTORY_MSG_PRSHARPEN_CONTRAST;PRS - Contrast threshold @@ -1942,9 +1944,13 @@ ZOOMPANEL_ZOOMOUT;Отдалить\nГорячая клавиша: - !TP_RAWEXPOS_RGB;Red, Green, Blue !TP_RAW_1PASSMEDIUM;1-Pass (Medium) !TP_RAW_3PASSBEST;3-Pass (Best) +!TP_RAW_4PASS;4-Pass +!TP_RAW_AMAZEVNG4;AMaZE+VNG4 +!TP_RAW_DUALDEMOSAICCONTRAST;Contrast threshold !TP_RAW_IMAGENUM;Sub-image !TP_RAW_IMAGENUM_TOOLTIP;Some raw files consist of several sub-images (Pentax/Sony Pixel Shift, Pentax 3-in-1 HDR, Canon Dual Pixel).\n\nWhen using any demosaicing method other than Pixel Shift, this selects which sub-image is used.\n\nWhen using the Pixel Shift demosaicing method on a Pixel Shift raw, all sub-images are used, and this selects which sub-image should be used for moving parts. !TP_RAW_PIXELSHIFTBLUR;Blur motion mask +!TP_RAW_PIXELSHIFTDMETHOD;Demosaic method for motion !TP_RAW_PIXELSHIFTEPERISO;Sensitivity !TP_RAW_PIXELSHIFTEPERISO_TOOLTIP;The default value of 0 should work fine for base ISO.\nHigher values increase sensitivity of motion detection.\nChange in small steps and watch the motion mask while changing.\nIncrease sensitivity for underexposed or high ISO images. !TP_RAW_PIXELSHIFTEQUALBRIGHT;Equalize brightness of frames diff --git a/rtdata/languages/Serbian (Cyrilic Characters) b/rtdata/languages/Serbian (Cyrilic Characters) index 863fc6a69..ddfb8b80d 100644 --- a/rtdata/languages/Serbian (Cyrilic Characters) +++ b/rtdata/languages/Serbian (Cyrilic Characters) @@ -1559,6 +1559,7 @@ ZOOMPANEL_ZOOMOUT;Умањује приказ слике - !HISTORY_MSG_493;L*a*b* Adjustments !HISTORY_MSG_CLAMPOOG;Out-of-gamut color clipping !HISTORY_MSG_COLORTONING_LABGRID_VALUE;CT - Color correction +!HISTORY_MSG_DUALDEMOSAIC_CONTRAST;AMaZE+VNG4 - Contrast threshold !HISTORY_MSG_HISTMATCHING;Auto-Matched Tone Curve !HISTORY_MSG_LOCALCONTRAST_AMOUNT;Local Contrast - Amount !HISTORY_MSG_LOCALCONTRAST_DARKNESS;Local Contrast - Darkness @@ -1567,6 +1568,7 @@ ZOOMPANEL_ZOOMOUT;Умањује приказ слике - !HISTORY_MSG_LOCALCONTRAST_RADIUS;Local Contrast - Radius !HISTORY_MSG_METADATA_MODE;Metadata copy mode !HISTORY_MSG_MICROCONTRAST_CONTRAST;Microcontrast - Contrast threshold +!HISTORY_MSG_PIXELSHIFT_DEMOSAIC;PS - Demosaic method for motion !HISTORY_MSG_PREPROCESS_LINEDENOISE_DIRECTION;Line noise filter direction !HISTORY_MSG_PREPROCESS_PDAFLINESFILTER;PDAF lines filter !HISTORY_MSG_PRSHARPEN_CONTRAST;PRS - Contrast threshold @@ -1916,9 +1918,12 @@ ZOOMPANEL_ZOOMOUT;Умањује приказ слике - !TP_RAWEXPOS_RGB;Red, Green, Blue !TP_RAW_1PASSMEDIUM;1-Pass (Medium) !TP_RAW_3PASSBEST;3-Pass (Best) +!TP_RAW_4PASS;4-Pass !TP_RAW_AHD;AHD !TP_RAW_AMAZE;AMaZE +!TP_RAW_AMAZEVNG4;AMaZE+VNG4 !TP_RAW_DCB;DCB +!TP_RAW_DUALDEMOSAICCONTRAST;Contrast threshold !TP_RAW_EAHD;EAHD !TP_RAW_FAST;Fast !TP_RAW_HD;Threshold @@ -1932,6 +1937,7 @@ ZOOMPANEL_ZOOMOUT;Умањује приказ слике - !TP_RAW_NONE;None (Shows sensor pattern) !TP_RAW_PIXELSHIFT;Pixel Shift !TP_RAW_PIXELSHIFTBLUR;Blur motion mask +!TP_RAW_PIXELSHIFTDMETHOD;Demosaic method for motion !TP_RAW_PIXELSHIFTEPERISO;Sensitivity !TP_RAW_PIXELSHIFTEPERISO_TOOLTIP;The default value of 0 should work fine for base ISO.\nHigher values increase sensitivity of motion detection.\nChange in small steps and watch the motion mask while changing.\nIncrease sensitivity for underexposed or high ISO images. !TP_RAW_PIXELSHIFTEQUALBRIGHT;Equalize brightness of frames diff --git a/rtdata/languages/Serbian (Latin Characters) b/rtdata/languages/Serbian (Latin Characters) index d0d7f4155..3af583ba8 100644 --- a/rtdata/languages/Serbian (Latin Characters) +++ b/rtdata/languages/Serbian (Latin Characters) @@ -1559,6 +1559,7 @@ ZOOMPANEL_ZOOMOUT;Umanjuje prikaz slike - !HISTORY_MSG_493;L*a*b* Adjustments !HISTORY_MSG_CLAMPOOG;Out-of-gamut color clipping !HISTORY_MSG_COLORTONING_LABGRID_VALUE;CT - Color correction +!HISTORY_MSG_DUALDEMOSAIC_CONTRAST;AMaZE+VNG4 - Contrast threshold !HISTORY_MSG_HISTMATCHING;Auto-Matched Tone Curve !HISTORY_MSG_LOCALCONTRAST_AMOUNT;Local Contrast - Amount !HISTORY_MSG_LOCALCONTRAST_DARKNESS;Local Contrast - Darkness @@ -1567,6 +1568,7 @@ ZOOMPANEL_ZOOMOUT;Umanjuje prikaz slike - !HISTORY_MSG_LOCALCONTRAST_RADIUS;Local Contrast - Radius !HISTORY_MSG_METADATA_MODE;Metadata copy mode !HISTORY_MSG_MICROCONTRAST_CONTRAST;Microcontrast - Contrast threshold +!HISTORY_MSG_PIXELSHIFT_DEMOSAIC;PS - Demosaic method for motion !HISTORY_MSG_PREPROCESS_LINEDENOISE_DIRECTION;Line noise filter direction !HISTORY_MSG_PREPROCESS_PDAFLINESFILTER;PDAF lines filter !HISTORY_MSG_PRSHARPEN_CONTRAST;PRS - Contrast threshold @@ -1916,9 +1918,12 @@ ZOOMPANEL_ZOOMOUT;Umanjuje prikaz slike - !TP_RAWEXPOS_RGB;Red, Green, Blue !TP_RAW_1PASSMEDIUM;1-Pass (Medium) !TP_RAW_3PASSBEST;3-Pass (Best) +!TP_RAW_4PASS;4-Pass !TP_RAW_AHD;AHD !TP_RAW_AMAZE;AMaZE +!TP_RAW_AMAZEVNG4;AMaZE+VNG4 !TP_RAW_DCB;DCB +!TP_RAW_DUALDEMOSAICCONTRAST;Contrast threshold !TP_RAW_EAHD;EAHD !TP_RAW_FAST;Fast !TP_RAW_HD;Threshold @@ -1932,6 +1937,7 @@ ZOOMPANEL_ZOOMOUT;Umanjuje prikaz slike - !TP_RAW_NONE;None (Shows sensor pattern) !TP_RAW_PIXELSHIFT;Pixel Shift !TP_RAW_PIXELSHIFTBLUR;Blur motion mask +!TP_RAW_PIXELSHIFTDMETHOD;Demosaic method for motion !TP_RAW_PIXELSHIFTEPERISO;Sensitivity !TP_RAW_PIXELSHIFTEPERISO_TOOLTIP;The default value of 0 should work fine for base ISO.\nHigher values increase sensitivity of motion detection.\nChange in small steps and watch the motion mask while changing.\nIncrease sensitivity for underexposed or high ISO images. !TP_RAW_PIXELSHIFTEQUALBRIGHT;Equalize brightness of frames diff --git a/rtdata/languages/Slovak b/rtdata/languages/Slovak index edccb8924..3ba135a71 100644 --- a/rtdata/languages/Slovak +++ b/rtdata/languages/Slovak @@ -1041,6 +1041,7 @@ ZOOMPANEL_ZOOMOUT;Oddialiť - !HISTORY_MSG_493;L*a*b* Adjustments !HISTORY_MSG_CLAMPOOG;Out-of-gamut color clipping !HISTORY_MSG_COLORTONING_LABGRID_VALUE;CT - Color correction +!HISTORY_MSG_DUALDEMOSAIC_CONTRAST;AMaZE+VNG4 - Contrast threshold !HISTORY_MSG_HISTMATCHING;Auto-Matched Tone Curve !HISTORY_MSG_LOCALCONTRAST_AMOUNT;Local Contrast - Amount !HISTORY_MSG_LOCALCONTRAST_DARKNESS;Local Contrast - Darkness @@ -1049,6 +1050,7 @@ ZOOMPANEL_ZOOMOUT;Oddialiť - !HISTORY_MSG_LOCALCONTRAST_RADIUS;Local Contrast - Radius !HISTORY_MSG_METADATA_MODE;Metadata copy mode !HISTORY_MSG_MICROCONTRAST_CONTRAST;Microcontrast - Contrast threshold +!HISTORY_MSG_PIXELSHIFT_DEMOSAIC;PS - Demosaic method for motion !HISTORY_MSG_PREPROCESS_LINEDENOISE_DIRECTION;Line noise filter direction !HISTORY_MSG_PREPROCESS_PDAFLINESFILTER;PDAF lines filter !HISTORY_MSG_PRSHARPEN_CONTRAST;PRS - Contrast threshold @@ -1827,12 +1829,15 @@ ZOOMPANEL_ZOOMOUT;Oddialiť - !TP_RAWEXPOS_TWOGREEN;Link greens !TP_RAW_1PASSMEDIUM;1-Pass (Medium) !TP_RAW_3PASSBEST;3-Pass (Best) +!TP_RAW_4PASS;4-Pass !TP_RAW_AHD;AHD !TP_RAW_AMAZE;AMaZE +!TP_RAW_AMAZEVNG4;AMaZE+VNG4 !TP_RAW_DCB;DCB !TP_RAW_DMETHOD_PROGRESSBAR;%1 demosaicing... !TP_RAW_DMETHOD_PROGRESSBAR_REFINE;Demosaicing refinement... !TP_RAW_DMETHOD_TOOLTIP;Note: IGV and LMMSE are dedicated to high ISO images to aid in noise reduction without leading to maze patterns, posterization or a washed-out look.\nPixel Shift is for Pentax/Sony Pixel Shift files. It falls back to AMaZE for non-Pixel Shift files. +!TP_RAW_DUALDEMOSAICCONTRAST;Contrast threshold !TP_RAW_EAHD;EAHD !TP_RAW_FAST;Fast !TP_RAW_HD;Threshold @@ -1849,6 +1854,7 @@ ZOOMPANEL_ZOOMOUT;Oddialiť - !TP_RAW_NONE;None (Shows sensor pattern) !TP_RAW_PIXELSHIFT;Pixel Shift !TP_RAW_PIXELSHIFTBLUR;Blur motion mask +!TP_RAW_PIXELSHIFTDMETHOD;Demosaic method for motion !TP_RAW_PIXELSHIFTEPERISO;Sensitivity !TP_RAW_PIXELSHIFTEPERISO_TOOLTIP;The default value of 0 should work fine for base ISO.\nHigher values increase sensitivity of motion detection.\nChange in small steps and watch the motion mask while changing.\nIncrease sensitivity for underexposed or high ISO images. !TP_RAW_PIXELSHIFTEQUALBRIGHT;Equalize brightness of frames diff --git a/rtdata/languages/Suomi b/rtdata/languages/Suomi index d1e898b91..ce22a396b 100644 --- a/rtdata/languages/Suomi +++ b/rtdata/languages/Suomi @@ -980,6 +980,7 @@ TP_WBALANCE_TEMPERATURE;Lämpötila [K] !HISTORY_MSG_493;L*a*b* Adjustments !HISTORY_MSG_CLAMPOOG;Out-of-gamut color clipping !HISTORY_MSG_COLORTONING_LABGRID_VALUE;CT - Color correction +!HISTORY_MSG_DUALDEMOSAIC_CONTRAST;AMaZE+VNG4 - Contrast threshold !HISTORY_MSG_HISTMATCHING;Auto-Matched Tone Curve !HISTORY_MSG_LOCALCONTRAST_AMOUNT;Local Contrast - Amount !HISTORY_MSG_LOCALCONTRAST_DARKNESS;Local Contrast - Darkness @@ -988,6 +989,7 @@ TP_WBALANCE_TEMPERATURE;Lämpötila [K] !HISTORY_MSG_LOCALCONTRAST_RADIUS;Local Contrast - Radius !HISTORY_MSG_METADATA_MODE;Metadata copy mode !HISTORY_MSG_MICROCONTRAST_CONTRAST;Microcontrast - Contrast threshold +!HISTORY_MSG_PIXELSHIFT_DEMOSAIC;PS - Demosaic method for motion !HISTORY_MSG_PREPROCESS_LINEDENOISE_DIRECTION;Line noise filter direction !HISTORY_MSG_PREPROCESS_PDAFLINESFILTER;PDAF lines filter !HISTORY_MSG_PRSHARPEN_CONTRAST;PRS - Contrast threshold @@ -1813,14 +1815,17 @@ TP_WBALANCE_TEMPERATURE;Lämpötila [K] !TP_RAWEXPOS_TWOGREEN;Link greens !TP_RAW_1PASSMEDIUM;1-Pass (Medium) !TP_RAW_3PASSBEST;3-Pass (Best) +!TP_RAW_4PASS;4-Pass !TP_RAW_AHD;AHD !TP_RAW_AMAZE;AMaZE +!TP_RAW_AMAZEVNG4;AMaZE+VNG4 !TP_RAW_DCB;DCB !TP_RAW_DCBENHANCE;DCB enhancement !TP_RAW_DCBITERATIONS;Number of DCB iterations !TP_RAW_DMETHOD_PROGRESSBAR;%1 demosaicing... !TP_RAW_DMETHOD_PROGRESSBAR_REFINE;Demosaicing refinement... !TP_RAW_DMETHOD_TOOLTIP;Note: IGV and LMMSE are dedicated to high ISO images to aid in noise reduction without leading to maze patterns, posterization or a washed-out look.\nPixel Shift is for Pentax/Sony Pixel Shift files. It falls back to AMaZE for non-Pixel Shift files. +!TP_RAW_DUALDEMOSAICCONTRAST;Contrast threshold !TP_RAW_EAHD;EAHD !TP_RAW_FAST;Fast !TP_RAW_HD;Threshold @@ -1837,6 +1842,7 @@ TP_WBALANCE_TEMPERATURE;Lämpötila [K] !TP_RAW_NONE;None (Shows sensor pattern) !TP_RAW_PIXELSHIFT;Pixel Shift !TP_RAW_PIXELSHIFTBLUR;Blur motion mask +!TP_RAW_PIXELSHIFTDMETHOD;Demosaic method for motion !TP_RAW_PIXELSHIFTEPERISO;Sensitivity !TP_RAW_PIXELSHIFTEPERISO_TOOLTIP;The default value of 0 should work fine for base ISO.\nHigher values increase sensitivity of motion detection.\nChange in small steps and watch the motion mask while changing.\nIncrease sensitivity for underexposed or high ISO images. !TP_RAW_PIXELSHIFTEQUALBRIGHT;Equalize brightness of frames diff --git a/rtdata/languages/Swedish b/rtdata/languages/Swedish index ee93aa468..819cf8340 100644 --- a/rtdata/languages/Swedish +++ b/rtdata/languages/Swedish @@ -1945,6 +1945,7 @@ ZOOMPANEL_ZOOMOUT;Förminska.\nKortkommando: - !HISTORY_MSG_493;L*a*b* Adjustments !HISTORY_MSG_CLAMPOOG;Out-of-gamut color clipping !HISTORY_MSG_COLORTONING_LABGRID_VALUE;CT - Color correction +!HISTORY_MSG_DUALDEMOSAIC_CONTRAST;AMaZE+VNG4 - Contrast threshold !HISTORY_MSG_HISTMATCHING;Auto-Matched Tone Curve !HISTORY_MSG_LOCALCONTRAST_AMOUNT;Local Contrast - Amount !HISTORY_MSG_LOCALCONTRAST_DARKNESS;Local Contrast - Darkness @@ -1953,6 +1954,7 @@ ZOOMPANEL_ZOOMOUT;Förminska.\nKortkommando: - !HISTORY_MSG_LOCALCONTRAST_RADIUS;Local Contrast - Radius !HISTORY_MSG_METADATA_MODE;Metadata copy mode !HISTORY_MSG_MICROCONTRAST_CONTRAST;Microcontrast - Contrast threshold +!HISTORY_MSG_PIXELSHIFT_DEMOSAIC;PS - Demosaic method for motion !HISTORY_MSG_PREPROCESS_LINEDENOISE_DIRECTION;Line noise filter direction !HISTORY_MSG_PREPROCESS_PDAFLINESFILTER;PDAF lines filter !HISTORY_MSG_PRSHARPEN_CONTRAST;PRS - Contrast threshold @@ -2108,9 +2110,12 @@ ZOOMPANEL_ZOOMOUT;Förminska.\nKortkommando: - !TP_PREPROCESS_PDAFLINESFILTER_TOOLTIP;Tries to suppress stripe noise caused by on-sensor PDAF pixels, occurring with some Sony mirrorless cameras on some backlit scenes with visible flare. !TP_RAW_1PASSMEDIUM;1-Pass (Medium) !TP_RAW_3PASSBEST;3-Pass (Best) +!TP_RAW_4PASS;4-Pass !TP_RAW_AHD;AHD !TP_RAW_AMAZE;AMaZE +!TP_RAW_AMAZEVNG4;AMaZE+VNG4 !TP_RAW_DCB;DCB +!TP_RAW_DUALDEMOSAICCONTRAST;Contrast threshold !TP_RAW_EAHD;EAHD !TP_RAW_FAST;Fast !TP_RAW_HPHD;HPHD @@ -2122,6 +2127,7 @@ ZOOMPANEL_ZOOMOUT;Förminska.\nKortkommando: - !TP_RAW_NONE;None (Shows sensor pattern) !TP_RAW_PIXELSHIFT;Pixel Shift !TP_RAW_PIXELSHIFTBLUR;Blur motion mask +!TP_RAW_PIXELSHIFTDMETHOD;Demosaic method for motion !TP_RAW_PIXELSHIFTEPERISO;Sensitivity !TP_RAW_PIXELSHIFTEPERISO_TOOLTIP;The default value of 0 should work fine for base ISO.\nHigher values increase sensitivity of motion detection.\nChange in small steps and watch the motion mask while changing.\nIncrease sensitivity for underexposed or high ISO images. !TP_RAW_PIXELSHIFTEQUALBRIGHT;Equalize brightness of frames diff --git a/rtdata/languages/Turkish b/rtdata/languages/Turkish index 9ae60cf81..e57ab4c1e 100644 --- a/rtdata/languages/Turkish +++ b/rtdata/languages/Turkish @@ -979,6 +979,7 @@ TP_WBALANCE_TEMPERATURE;Isı !HISTORY_MSG_493;L*a*b* Adjustments !HISTORY_MSG_CLAMPOOG;Out-of-gamut color clipping !HISTORY_MSG_COLORTONING_LABGRID_VALUE;CT - Color correction +!HISTORY_MSG_DUALDEMOSAIC_CONTRAST;AMaZE+VNG4 - Contrast threshold !HISTORY_MSG_HISTMATCHING;Auto-Matched Tone Curve !HISTORY_MSG_LOCALCONTRAST_AMOUNT;Local Contrast - Amount !HISTORY_MSG_LOCALCONTRAST_DARKNESS;Local Contrast - Darkness @@ -987,6 +988,7 @@ TP_WBALANCE_TEMPERATURE;Isı !HISTORY_MSG_LOCALCONTRAST_RADIUS;Local Contrast - Radius !HISTORY_MSG_METADATA_MODE;Metadata copy mode !HISTORY_MSG_MICROCONTRAST_CONTRAST;Microcontrast - Contrast threshold +!HISTORY_MSG_PIXELSHIFT_DEMOSAIC;PS - Demosaic method for motion !HISTORY_MSG_PREPROCESS_LINEDENOISE_DIRECTION;Line noise filter direction !HISTORY_MSG_PREPROCESS_PDAFLINESFILTER;PDAF lines filter !HISTORY_MSG_PRSHARPEN_CONTRAST;PRS - Contrast threshold @@ -1812,14 +1814,17 @@ TP_WBALANCE_TEMPERATURE;Isı !TP_RAWEXPOS_TWOGREEN;Link greens !TP_RAW_1PASSMEDIUM;1-Pass (Medium) !TP_RAW_3PASSBEST;3-Pass (Best) +!TP_RAW_4PASS;4-Pass !TP_RAW_AHD;AHD !TP_RAW_AMAZE;AMaZE +!TP_RAW_AMAZEVNG4;AMaZE+VNG4 !TP_RAW_DCB;DCB !TP_RAW_DCBENHANCE;DCB enhancement !TP_RAW_DCBITERATIONS;Number of DCB iterations !TP_RAW_DMETHOD_PROGRESSBAR;%1 demosaicing... !TP_RAW_DMETHOD_PROGRESSBAR_REFINE;Demosaicing refinement... !TP_RAW_DMETHOD_TOOLTIP;Note: IGV and LMMSE are dedicated to high ISO images to aid in noise reduction without leading to maze patterns, posterization or a washed-out look.\nPixel Shift is for Pentax/Sony Pixel Shift files. It falls back to AMaZE for non-Pixel Shift files. +!TP_RAW_DUALDEMOSAICCONTRAST;Contrast threshold !TP_RAW_EAHD;EAHD !TP_RAW_FAST;Fast !TP_RAW_HD;Threshold @@ -1836,6 +1841,7 @@ TP_WBALANCE_TEMPERATURE;Isı !TP_RAW_NONE;None (Shows sensor pattern) !TP_RAW_PIXELSHIFT;Pixel Shift !TP_RAW_PIXELSHIFTBLUR;Blur motion mask +!TP_RAW_PIXELSHIFTDMETHOD;Demosaic method for motion !TP_RAW_PIXELSHIFTEPERISO;Sensitivity !TP_RAW_PIXELSHIFTEPERISO_TOOLTIP;The default value of 0 should work fine for base ISO.\nHigher values increase sensitivity of motion detection.\nChange in small steps and watch the motion mask while changing.\nIncrease sensitivity for underexposed or high ISO images. !TP_RAW_PIXELSHIFTEQUALBRIGHT;Equalize brightness of frames From 1b094a084a2886a0f299f19cc688d8f7866ba8c4 Mon Sep 17 00:00:00 2001 From: heckflosse Date: Wed, 13 Jun 2018 13:02:10 +0200 Subject: [PATCH 38/42] Show/hide contrast mask, still wrong icon on button --- rtgui/imagearea.cc | 8 ++++++++ rtgui/imagearea.h | 1 + rtgui/imageareatoollistener.h | 1 + rtgui/indclippedpanel.cc | 1 + rtgui/toolpanelcoord.cc | 10 ++++++++++ rtgui/toolpanelcoord.h | 1 + 6 files changed, 22 insertions(+) diff --git a/rtgui/imagearea.cc b/rtgui/imagearea.cc index 038e04629..56d81a686 100644 --- a/rtgui/imagearea.cc +++ b/rtgui/imagearea.cc @@ -560,6 +560,14 @@ void ImageArea::spotWBSelected (int x, int y) } } +void ImageArea::sharpMaskSelected (bool sharpMask) +{ + + if (listener) { + listener->sharpMaskSelected (sharpMask); + } +} + void ImageArea::getScrollImageSize (int& w, int& h) { diff --git a/rtgui/imagearea.h b/rtgui/imagearea.h index 65fc14cce..de9ba1f71 100644 --- a/rtgui/imagearea.h +++ b/rtgui/imagearea.h @@ -131,6 +131,7 @@ public: void setToolHand (); void straightenReady (double rotDeg); void spotWBSelected (int x, int y); + void sharpMaskSelected (bool sharpMask); int getSpotWBRectSize (); void redraw (); diff --git a/rtgui/imageareatoollistener.h b/rtgui/imageareatoollistener.h index b7d5cec94..d11ec2e6f 100644 --- a/rtgui/imageareatoollistener.h +++ b/rtgui/imageareatoollistener.h @@ -29,6 +29,7 @@ class ImageAreaToolListener public: virtual ~ImageAreaToolListener() {} virtual void spotWBselected (int x, int y, Thumbnail* thm = nullptr) {} + virtual void sharpMaskSelected (bool sharpMask) {} virtual int getSpotWBRectSize () { return 8; diff --git a/rtgui/indclippedpanel.cc b/rtgui/indclippedpanel.cc index 35cfa843d..1ccc79edf 100644 --- a/rtgui/indclippedpanel.cc +++ b/rtgui/indclippedpanel.cc @@ -127,6 +127,7 @@ void IndicateClippedPanel::buttonToggled (Gtk::ToggleButton* tb) indClippedH->set_active(false); } previewFocusMask->set_active(false); + imageArea->sharpMaskSelected(previewSharpMask->get_active()); } else { previewFocusMask->set_active(false); previewSharpMask->set_active(false); diff --git a/rtgui/toolpanelcoord.cc b/rtgui/toolpanelcoord.cc index 2899625fe..8ed9fc6e2 100644 --- a/rtgui/toolpanelcoord.cc +++ b/rtgui/toolpanelcoord.cc @@ -656,6 +656,16 @@ void ToolPanelCoordinator::spotWBselected (int x, int y, Thumbnail* thm) } } +void ToolPanelCoordinator::sharpMaskSelected(bool sharpMask) +{ + + if (!ipc) { + return; + } + ipc->beginUpdateParams (); + ipc->setSharpMask(sharpMask); + ipc->endUpdateParams (rtengine::EvShrEnabled); +} diff --git a/rtgui/toolpanelcoord.h b/rtgui/toolpanelcoord.h index 5b9822ef2..eca868b5e 100644 --- a/rtgui/toolpanelcoord.h +++ b/rtgui/toolpanelcoord.h @@ -280,6 +280,7 @@ public: // imageareatoollistener interface void spotWBselected (int x, int y, Thumbnail* thm = nullptr); + void sharpMaskSelected (bool sharpMask); void cropSelectionReady (); void rotateSelectionReady (double rotate_deg, Thumbnail* thm = nullptr); ToolBar* getToolBar () From 306e0478d742f1e826b37e0027b5fe69aebbeb88 Mon Sep 17 00:00:00 2001 From: heckflosse Date: Wed, 13 Jun 2018 14:28:31 +0200 Subject: [PATCH 39/42] deconvolution amount was ignored if contrast threshold == 0, fixed --- rtengine/ipsharpen.cc | 2 +- rtengine/rt_algo.cc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/rtengine/ipsharpen.cc b/rtengine/ipsharpen.cc index 89f497c8e..eaf0db732 100644 --- a/rtengine/ipsharpen.cc +++ b/rtengine/ipsharpen.cc @@ -222,7 +222,7 @@ void ImProcFunctions::sharpening (LabImage* lab, const SharpeningParams &sharpen if(showMask) { // calculate contrast based blend factors to reduce sharpening in regions with low contrast JaggedArray blend(W, H); - buildBlendMask(lab->L, blend, W, H, sharpenParam.contrast / 100.f); + buildBlendMask(lab->L, blend, W, H, sharpenParam.contrast / 100.f, sharpenParam.method == "rld" ? sharpenParam.deconvamount / 100.0 : 1.f); #ifdef _OPENMP #pragma omp parallel for #endif diff --git a/rtengine/rt_algo.cc b/rtengine/rt_algo.cc index 21c8eac12..cff145de8 100644 --- a/rtengine/rt_algo.cc +++ b/rtengine/rt_algo.cc @@ -193,7 +193,7 @@ void buildBlendMask(float** luminance, rtengine::JaggedArray &blend, int if(contrastThreshold == 0.f) { for(int j = 0; j < H; ++j) { for(int i = 0; i < W; ++i) { - blend[j][i] = 1.f; + blend[j][i] = amount; } } } else { From ebfc5dab9bb731c05afd7a89999549463a4a8a5a Mon Sep 17 00:00:00 2001 From: heckflosse Date: Wed, 13 Jun 2018 22:27:29 +0200 Subject: [PATCH 40/42] Info area hidden by detail window, fixes #4606 --- rtgui/imagearea.cc | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/rtgui/imagearea.cc b/rtgui/imagearea.cc index 038e04629..0818d7475 100644 --- a/rtgui/imagearea.cc +++ b/rtgui/imagearea.cc @@ -241,13 +241,14 @@ bool ImageArea::on_draw(const ::Cairo::RefPtr< Cairo::Context> &cr) mainCropWindow->expose (cr); } + for (std::list::reverse_iterator i = cropWins.rbegin(); i != cropWins.rend(); ++i) { + (*i)->expose (cr); + } + if (options.showInfo && infotext != "") { iBackBuffer.copySurface(cr); } - for (std::list::reverse_iterator i = cropWins.rbegin(); i != cropWins.rend(); ++i) { - (*i)->expose (cr); - } return true; } From 35743a19ad0429d5201619ec006e5c84c065c6b1 Mon Sep 17 00:00:00 2001 From: heckflosse Date: Thu, 14 Jun 2018 00:31:11 +0200 Subject: [PATCH 41/42] fixed copy/paste bug in gauss.cc --- rtengine/gauss.cc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/rtengine/gauss.cc b/rtengine/gauss.cc index 2468e52d2..32328b06f 100644 --- a/rtengine/gauss.cc +++ b/rtengine/gauss.cc @@ -1020,14 +1020,14 @@ template void gaussVerticaldiv (T** src, T** dst, T** divBuffer, const } for (int k = 0; k < numcols; k++) { - rtengine::max(dst[H - 1][i + k] = divBuffer[H - 1][i + k] / (temp2[H - 1][k] = temp2Hm1[k]), 0.f); - rtengine::max(dst[H - 2][i + k] = divBuffer[H - 2][i + k] / (temp2[H - 2][k] = B * temp2[H - 2][k] + b1 * temp2[H - 1][k] + b2 * temp2H[k] + b3 * temp2Hp1[k]), 0.f); - rtengine::max(dst[H - 3][i + k] = divBuffer[H - 3][i + k] / (temp2[H - 3][k] = B * temp2[H - 3][k] + b1 * temp2[H - 2][k] + b2 * temp2[H - 1][k] + b3 * temp2H[k], 0.f); + dst[H - 1][i + k] = rtengine::max(divBuffer[H - 1][i + k] / (temp2[H - 1][k] = temp2Hm1[k]), 0.f); + dst[H - 2][i + k] = rtengine::max(divBuffer[H - 2][i + k] / (temp2[H - 2][k] = B * temp2[H - 2][k] + b1 * temp2[H - 1][k] + b2 * temp2H[k] + b3 * temp2Hp1[k]), 0.f); + dst[H - 3][i + k] = rtengine::max(divBuffer[H - 3][i + k] / (temp2[H - 3][k] = B * temp2[H - 3][k] + b1 * temp2[H - 2][k] + b2 * temp2[H - 1][k] + b3 * temp2H[k]), 0.f); } for (int j = H - 4; j >= 0; j--) { for (int k = 0; k < numcols; k++) { - rtengine::max(dst[j][i + k] = divBuffer[j][i + k] / (temp2[j][k] = B * temp2[j][k] + b1 * temp2[j + 1][k] + b2 * temp2[j + 2][k] + b3 * temp2[j + 3][k]), 0.f); + dst[j][i + k] = rtengine::max(divBuffer[j][i + k] / (temp2[j][k] = B * temp2[j][k] + b1 * temp2[j + 1][k] + b2 * temp2[j + 2][k] + b3 * temp2[j + 3][k]), 0.f); } } } From e3cb9130a1b9c2154b3f6d4a7c4d4f81d708bc39 Mon Sep 17 00:00:00 2001 From: heckflosse Date: Thu, 14 Jun 2018 00:38:28 +0200 Subject: [PATCH 42/42] Fixed copy/paste bug in gauss.cc --- rtengine/gauss.cc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/rtengine/gauss.cc b/rtengine/gauss.cc index 32328b06f..170997a56 100644 --- a/rtengine/gauss.cc +++ b/rtengine/gauss.cc @@ -1050,12 +1050,12 @@ template void gaussVerticaldiv (T** src, T** dst, T** divBuffer, const double temp2H = src[H - 1][i] + M[1][0] * (temp2[H - 1][0] - src[H - 1][i]) + M[1][1] * (temp2[H - 2][0] - src[H - 1][i]) + M[1][2] * (temp2[H - 3][0] - src[H - 1][i]); double temp2Hp1 = src[H - 1][i] + M[2][0] * (temp2[H - 1][0] - src[H - 1][i]) + M[2][1] * (temp2[H - 2][0] - src[H - 1][i]) + M[2][2] * (temp2[H - 3][0] - src[H - 1][i]); - rtengine::max(dst[H - 1][i] = divBuffer[H - 1][i] / (temp2[H - 1][0] = temp2Hm1), 0.f); - rtengine::max(dst[H - 2][i] = divBuffer[H - 2][i] / (temp2[H - 2][0] = B * temp2[H - 2][0] + b1 * temp2[H - 1][0] + b2 * temp2H + b3 * temp2Hp1), 0.f); - rtengine::max(dst[H - 3][i] = divBuffer[H - 3][i] / (temp2[H - 3][0] = B * temp2[H - 3][0] + b1 * temp2[H - 2][0] + b2 * temp2[H - 1][0] + b3 * temp2H), 0.f); + dst[H - 1][i] = rtengine::max(divBuffer[H - 1][i] / (temp2[H - 1][0] = temp2Hm1), 0.f); + dst[H - 2][i] = rtengine::max(divBuffer[H - 2][i] / (temp2[H - 2][0] = B * temp2[H - 2][0] + b1 * temp2[H - 1][0] + b2 * temp2H + b3 * temp2Hp1), 0.f); + dst[H - 3][i] = rtengine::max(divBuffer[H - 3][i] / (temp2[H - 3][0] = B * temp2[H - 3][0] + b1 * temp2[H - 2][0] + b2 * temp2[H - 1][0] + b3 * temp2H), 0.f); for (int j = H - 4; j >= 0; j--) { - rtengine::max(dst[j][i] = divBuffer[j][i] / (temp2[j][0] = B * temp2[j][0] + b1 * temp2[j + 1][0] + b2 * temp2[j + 2][0] + b3 * temp2[j + 3][0]), 0.f); + dst[j][i] = rtengine::max(divBuffer[j][i] / (temp2[j][0] = B * temp2[j][0] + b1 * temp2[j + 1][0] + b2 * temp2[j + 2][0] + b3 * temp2[j + 3][0]), 0.f); } } }