diff --git a/rtdata/languages/default b/rtdata/languages/default index b9d3f03e3..d7653a230 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 @@ -735,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 @@ -1761,8 +1763,10 @@ 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 TP_RAW_DCB;DCB TP_RAW_DCBENHANCE;DCB enhancement TP_RAW_DCBITERATIONS;Number of DCB iterations @@ -1770,6 +1774,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 @@ -1787,6 +1792,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/CMakeLists.txt b/rtengine/CMakeLists.txt index 5ecd458be..67b07c48c 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 @@ -122,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/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 new file mode 100644 index 000000000..08e142a4e --- /dev/null +++ b/rtengine/amaze_vng4_demosaic_RT.cc @@ -0,0 +1,93 @@ +//////////////////////////////////////////////////////////////// +// +// combined AMaZE + VNG4 demosaic algorithm +// +// +// copyright (c) 2018 Ingo Weyrich +// +// blends AMaZE and VNG4 output based on contrast +// +// +// 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. +// +// 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" +//#define BENCHMARK +#include "StopWatch.h" +#include "rt_algo.h" + +using namespace std; + +namespace rtengine +{ + +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); + return; + } + + 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); + 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 use vng4 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 c4e3b6a68..3cedcaaa6 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)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]; + 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/demosaic_algos.cc b/rtengine/demosaic_algos.cc index 582b00629..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 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/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/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/ipsharpen.cc b/rtengine/ipsharpen.cc index 405f1bd80..855a8a8c9 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/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 dfcb91ebb..9f6f26cf5 100644 --- a/rtengine/procparams.cc +++ b/rtengine/procparams.cc @@ -33,7 +33,6 @@ #include "../rtgui/version.h" using namespace std; -extern Options options; namespace { @@ -2357,6 +2356,7 @@ RAWParams::BayerSensor::BayerSensor() : greenthresh(0), dcb_iterations(2), lmmse_iterations(2), + dualDemosaicContrast(20), pixelShiftMotionCorrectionMethod(PSMotionCorrectionMethod::AUTO), pixelShiftEperIso(0.0), pixelShiftSigma(1.0), @@ -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) { @@ -2392,6 +2392,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 @@ -2402,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; } @@ -2425,28 +2426,29 @@ 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() { static const std::vector method_strings { "amaze", - "igv", + "amazevng4", + "rcd", + "dcb", "lmmse", + "igv", + "ahd", "eahd", "hphd", "vng4", - "dcb", - "ahd", - "rcd", "fast", "mono", - "none", - "pixelshift" + "pixelshift", + "none" }; return method_strings; } @@ -2456,8 +2458,26 @@ 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)), + dualDemosaicContrast(20), ccSteps(0), blackred(0.0), blackgreen(0.0), @@ -2469,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 @@ -2483,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", @@ -3332,6 +3354,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); @@ -3342,12 +3365,13 @@ 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.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); @@ -4657,6 +4681,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"); @@ -4678,15 +4703,32 @@ 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); } 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 467ecf1e3..121fb8afa 100644 --- a/rtengine/procparams.h +++ b/rtengine/procparams.h @@ -1224,18 +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 + PIXELSHIFT, + NONE }; enum class PSMotionCorrectionMethod { @@ -1244,6 +1245,12 @@ struct RAWParams { CUSTOM }; + enum class PSDemosaicMethod { + AMAZE, + AMAZEVNG4, + LMMSE + }; + Glib::ustring method; int imageNum; int ccSteps; @@ -1263,6 +1270,7 @@ struct RAWParams { int greenthresh; int dcb_iterations; int lmmse_iterations; + double dualDemosaicContrast; PSMotionCorrectionMethod pixelShiftMotionCorrectionMethod; double pixelShiftEperIso; double pixelShiftSigma; @@ -1273,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; @@ -1289,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); }; /** @@ -1296,6 +1307,7 @@ struct RAWParams { */ struct XTransSensor { enum class Method { + FOUR_PASS, THREE_PASS, ONE_PASS, FAST, @@ -1304,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 6f119a2ad..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); } } @@ -2068,11 +2068,13 @@ 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) ) { 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, 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) ) { @@ -2097,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 0512af790..b5418d0ec 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]); @@ -262,12 +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, bool keepGreens = false); 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_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(); @@ -290,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/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/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); } 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/rtengine/vng4_demosaic_RT.cc b/rtengine/vng4_demosaic_RT.cc new file mode 100644 index 000000000..d6520607e --- /dev/null +++ b/rtengine/vng4_demosaic_RT.cc @@ -0,0 +1,344 @@ +//////////////////////////////////////////////////////////////// +// +// 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 "../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, bool keepGreens) +{ + 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 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 color = fc(row, col); + if (keepGreens && (color & 1)) { + green[row][col] = pix[color]; + } else { + 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; + 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); + } +} +} 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/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..fb92bbde0 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, 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], 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]); @@ -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 73fea1aa3..c6f04c053 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,11 @@ 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"); + 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); method = Gtk::manage (new MyComboBoxText ()); @@ -93,18 +99,37 @@ BayerProcess::BayerProcess () : FoldableToolPanel(this, "bayerprocess", M("TP_RA lmmseOptions->pack_start(*lmmseIterations); pack_start( *lmmseOptions, Gtk::PACK_SHRINK, 4); - pixelShiftFrame = Gtk::manage (new Gtk::VBox ()); - pixelShiftFrame->set_border_width(0); + dualDemosaicOptions = Gtk::manage (new Gtk::VBox ()); + + dualDemosaicContrast = Gtk::manage(new Adjuster (M("TP_RAW_DUALDEMOSAICCONTRAST"), 0, 100, 1, 20)); + dualDemosaicContrast->setAdjusterListener (this); + + if (dualDemosaicContrast->delay < options.adjusterMaxDelay) { + dualDemosaicContrast->delay = options.adjusterMaxDelay; + } + + dualDemosaicContrast->show(); + dualDemosaicOptions->pack_start(*dualDemosaicContrast); + pack_start( *dualDemosaicOptions, Gtk::PACK_SHRINK, 4); + + + // -------------------- 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); @@ -115,7 +140,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); @@ -123,12 +148,23 @@ 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 ()); + 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); @@ -188,14 +224,8 @@ 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); + pixelShiftMainVBox->pack_start(*pixelShiftOptions); + pixelShiftFrame->add(*pixelShiftMainVBox); pixelShiftOptions->hide(); pack_start( *pixelShiftFrame, Gtk::PACK_SHRINK, 4); @@ -203,6 +233,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) )); } @@ -211,9 +242,9 @@ 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()); imageNumber->set_active(pp->raw.bayersensor.imageNum); for (size_t i = 0; i < procparams::RAWParams::BayerSensor::getMethodStrings().size(); ++i) { @@ -223,31 +254,38 @@ void BayerProcess::read(const rtengine::procparams::ProcParams* pp, const Params break; } } + 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); 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); - 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); + 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); + 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); @@ -266,51 +304,44 @@ 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); 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); 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) { 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_text(M("GENERAL_UNCHANGED")); + } + } 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::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(); } - // 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)) @@ -323,6 +354,7 @@ void BayerProcess::read(const rtengine::procparams::ProcParams* pp, const Params method->block (false); imageNumber->block (false); + pixelShiftDemosaicMethod->block(false); //allEnhconn.block (false); enableListener (); @@ -335,6 +367,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(); @@ -345,31 +378,37 @@ 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 (); 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 && 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(); //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.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(); @@ -379,25 +418,49 @@ 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(); } } +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")); - 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_text(M("GENERAL_UNCHANGED")); // No name imageNumber->append (M("GENERAL_UNCHANGED")); imageNumber->set_active_text (M("GENERAL_UNCHANGED")); ToolPanel::setBatchMode (batchMode); ccSteps->showEditedCB (); dcbIterations->showEditedCB (); lmmseIterations->showEditedCB (); + dualDemosaicContrast->showEditedCB (); pixelShiftEperIso->showEditedCB (); pixelShiftSigma->showEditedCB (); } @@ -406,6 +469,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 +477,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 +500,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) { @@ -446,23 +514,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::PIXELSHIFT) { + if (currentMethod == procparams::RAWParams::BayerSensor::Method::AMAZEVNG4) { + dualDemosaicOptions->show(); + } else { + dualDemosaicOptions->hide(); + } + + if (currentMethod == procparams::RAWParams::BayerSensor::Method::PIXELSHIFT) { if(pixelShiftMotionMethod->get_active_row_number() == 2) { pixelShiftOptions->show(); } else { @@ -474,21 +548,22 @@ void BayerProcess::methodChanged () } } - Glib::ustring methodName = ""; - bool ppreq = false; - - 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; - } + 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 = curSelection; + oldMethod = currentSelection; - if (listener) { - listener->panelChanged (ppreq ? EvDemosaicMethodPreProc : EvDemosaicMethod, methodName); +} + +void BayerProcess::pixelShiftDemosaicMethodChanged () +{ + + if (listener && pixelShiftDemosaicMethod->get_active_row_number() >= 0) { + listener->panelChanged (EvDemosaicPixelshiftDemosaicMethod, pixelShiftDemosaicMethod->get_active_text()); } } @@ -536,10 +611,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); @@ -569,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 48b445d90..2b3e420bc 100644 --- a/rtgui/bayerprocess.h +++ b/rtgui/bayerprocess.h @@ -39,9 +39,10 @@ protected: CheckBox* dcbEnhance; Gtk::VBox *lmmseOptions; Adjuster* lmmseIterations; - Gtk::VBox *pixelShiftFrame; + Gtk::Frame *pixelShiftFrame; Gtk::VBox *pixelShiftOptions; MyComboBoxText* pixelShiftMotionMethod; + MyComboBoxText* pixelShiftDemosaicMethod; CheckBox* pixelShiftShowMotion; CheckBox* pixelShiftShowMotionMaskOnly; CheckBox* pixelShiftNonGreenCross; @@ -49,29 +50,35 @@ protected: CheckBox* pixelShiftBlur; CheckBox* pixelShiftHoleFill; CheckBox* pixelShiftMedian; - CheckBox* pixelShiftLmmse; CheckBox* pixelShiftEqualBright; CheckBox* pixelShiftEqualBrightChannel; Adjuster* pixelShiftSmooth; Adjuster* pixelShiftEperIso; Adjuster* pixelShiftSigma; + Gtk::VBox *dualDemosaicOptions; + Adjuster* dualDemosaicContrast; int oldMethod; IdleRegister idle_register; + rtengine::ProcEvent EvDemosaicContrast; + rtengine::ProcEvent EvDemosaicPixelshiftDemosaicMethod; 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 pixelShiftDemosaicMethodChanged(); void FrameCountChanged(int n, int frameNum); }; 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/paramsedited.cc b/rtgui/paramsedited.cc index 0eebe2e41..d14635d10 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; @@ -413,15 +414,16 @@ 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; raw.bayersensor.pdafLinesFilter = v; raw.xtranssensor.method = v; + raw.xtranssensor.dualDemosaicContrast = v; raw.xtranssensor.ccSteps = v; raw.xtranssensor.exBlackRed = v; raw.xtranssensor.exBlackGreen = v; @@ -952,6 +954,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; @@ -962,15 +965,16 @@ 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; 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; @@ -2496,6 +2500,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; } @@ -2536,10 +2544,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; } @@ -2552,6 +2556,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; } @@ -2572,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; } @@ -3072,9 +3084,9 @@ 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 + && 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 47fb70ef0..546a5c333 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; @@ -741,10 +742,10 @@ public: bool pixelShiftGreen; bool pixelShiftBlur; bool pixelShiftSmooth; - bool pixelShiftLmmse; bool pixelShiftEqualBright; bool pixelShiftEqualBrightChannel; bool pixelShiftNonGreenCross; + bool pixelShiftDemosaicMethod; //bool allEnhance; bool greenEq; @@ -760,6 +761,7 @@ public: public: bool method; + bool dualDemosaicContrast; bool ccSteps; bool exBlackRed; bool exBlackGreen; 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 e9f7ad60e..1fb34ca0a 100644 --- a/rtgui/ppversion.h +++ b/rtgui/ppversion.h @@ -1,11 +1,15 @@ #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 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 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..1b2b4a40d 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,19 @@ 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, 100, 1, 20)); + dualDemosaicContrast->setAdjusterListener (this); + + 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); @@ -83,8 +100,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); @@ -93,14 +108,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(std::numeric_limits::max()); // No name + 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); @@ -109,35 +128,47 @@ 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(); - 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.dualDemosaicContrast = dualDemosaicContrast->getEditedState (); pedited->raw.xtranssensor.ccSteps = ccSteps->getEditedState (); } } +void XTransProcess::setAdjusterBehavior (bool falsecoloradd, bool dualDemosaicContrastAdd) +{ + dualDemosaicContrast->setAddMode(dualDemosaicContrastAdd); + ccSteps->setAddMode(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); + 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 ); } } @@ -147,6 +178,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() ); } } } @@ -154,22 +187,22 @@ 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 (!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 + ? EvDemosaicMethodPreProc + : EvDemosaicMethod, method->get_active_text()); } } diff --git a/rtgui/xtransprocess.h b/rtgui/xtransprocess.h index 44ed2e670..edc0965b8 100644 --- a/rtgui/xtransprocess.h +++ b/rtgui/xtransprocess.h @@ -32,21 +32,25 @@ protected: MyComboBoxText* method; Adjuster* ccSteps; + Gtk::VBox *dualDemosaicOptions; + Adjuster* dualDemosaicContrast; int oldSelection; sigc::connection methodconn; + rtengine::ProcEvent EvDemosaicContrast; 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, bool dualDemosaicContrastAdd); + 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