86#define USE_NEW_IMPL_CL 0
96#define DT_IOP_DENOISE_PROFILE_INSET DT_PIXEL_APPLY_DPI(5)
97#define DT_IOP_DENOISE_PROFILE_RES 64
98#define DT_IOP_DENOISE_PROFILE_V8_BANDS 5
99#define DT_IOP_DENOISE_PROFILE_BANDS 7
108#define DT_IOP_DENOISE_PROFILE_P_FULCRUM 0.05f
123#define DT_DENOISE_PROFILE_NONE_V9 4
389 const float*
const restrict buf,
const int width,
const int height,
const int scale)
394 snprintf(filename,
sizeof(filename), namespec, scale);
395 FILE *
f = g_fopen(filename,
"wb");
400 for(
size_t k=0;
k<
n;
k++)
401 fwrite(buf+4U*
k,
sizeof(
float), 3,
f);
407#define debug_dump_PFM(p,n,b,w,h,s)
411 void *new_params,
const int new_version)
413 if((old_version == 1 || old_version == 2 || old_version == 3) && new_version == 4)
427 memcpy(
n->a, o->
a,
sizeof(
float) * 3);
428 memcpy(
n->b, o->
b,
sizeof(
float) * 3);
452 if(!memcmp(interpolated.
a, o->
a,
sizeof(
float) * 3) && !memcmp(interpolated.
b, o->
b,
sizeof(
float) * 3))
459 else if(new_version == 5)
469 memcpy(&v4, old_params,
sizeof(v4));
484 v5->
x[c][b] = v4.
x[c][b];
485 v5->
y[c][b] = v4.
y[c][b];
491 else if(new_version == 6)
497 if(
legacy_params(self, old_params, old_version, &v5, 5))
return 1;
500 memcpy(&v5, old_params,
sizeof(v5));
507 for(
int k = 0;
k < 3;
k++)
516 v6->
x[c][b] = v5.
x[c][b];
517 v6->
y[c][b] = v5.
y[c][b];
523 else if(new_version == 7)
529 if(
legacy_params(self, old_params, old_version, &v6, 6))
return 1;
532 memcpy(&v6, old_params,
sizeof(v6));
538 for(
int k = 0;
k < 3;
k++)
547 v7->
x[c][b] = v6.
x[c][b];
548 v7->
y[c][b] = v6.
y[c][b];
557 else if(new_version == 8)
563 if(
legacy_params(self, old_params, old_version, &v7, 7))
return 1;
566 memcpy(&v7, old_params,
sizeof(v7));
572 for(
int k = 0;
k < 3;
k++)
581 v8->
x[c][b] = v7.
x[c][b];
582 v8->
y[c][b] = v7.
y[c][b];
595 else if(new_version == 9)
601 if(
legacy_params(self, old_params, old_version, &v8, 8))
return 1;
604 memcpy(&v8, old_params,
sizeof(v8));
610 for(
int k = 0;
k < 3;
k++)
640 else if(new_version == 10)
646 if(
legacy_params(self, old_params, old_version, &v9, 9))
return 1;
649 memcpy(&v9, old_params,
sizeof(v9));
660 for(
int k = 0;
k < 3;
k++)
669 v10->
x[c][b] = v9.
x[c][b];
670 v10->
y[c][b] = v9.
y[c][b];
689 else if(new_version == 11)
695 if(
legacy_params(self, old_params, old_version, v11, 10))
return 1;
698 memcpy(v11, old_params,
sizeof(*v11));
704 const float compensate_strength = 2.5f;
705 v11->
strength /= compensate_strength;
715 memset(&
p, 0,
sizeof(
p));
725 p.use_new_vst =
TRUE;
731 p.wb_adaptive_anscombe =
TRUE;
733 p.central_pixel_weight = 0.1f;
734 p.overshooting = 1.0f;
735 p.fix_anscombe_and_nlmeans_norm =
TRUE;
752 return _(
"de_noise (profiled)");
758 _(
"denoise using noise statistics profiled on sensors"),
760 _(
"linear, RGB, scene-referred"),
762 _(
"linear, RGB, scene-referred"));
793 const int P = ceilf(
d->radius * fminf(fminf(roi_in->
scale, 2.0f), 1.0f));
794 const int K = ceilf(
d->nbhood * fminf(fminf(roi_in->
scale, 2.0f), 1.0f));
795 const int K_scattered = ceilf(
d->scattering * (K * K * K + 7.0 * K * sqrt(K)) / 6.0) + K;
797 tiling->factor = 2.0f + 0.25f;
801 tiling->overlap =
P + K_scattered;
809 const float scale = fminf(roi_in->
scale, 1.0f);
812 = fminf(2 * (2u << (max_max_scale - 1)) + 1,
814 const float i0 = dt_log2f((supp0 - 1.0f) * .5f);
815 for(; max_scale < max_max_scale; max_scale++)
818 const float supp = 2 * (2u << max_scale) + 1;
820 const float supp_in = supp * (1.0f / scale);
821 const float i_in = dt_log2f((supp_in - 1) * .5f) - 1.0f;
823 const float t = 1.0f - (i_in + .5f) / i0;
827 const int max_filter_radius = (1u << max_scale);
830 tiling->factor_cl = 3.5f + max_scale;
834 tiling->overlap = max_filter_radius;
842static inline void precondition(
const float *
const in,
float *
const buf,
const int wd,
const int ht,
846 = { (b[0] / a[0]) * (b[0] / a[0]) + 3.f / 8.f,
847 (b[1] / a[1]) * (b[1] / a[1]) + 3.f / 8.f,
848 (b[2] / a[2]) * (b[2] / a[2]) + 3.f / 8.f,
850 const size_t npixels = (size_t)wd * ht;
852 for(
size_t j = 0; j < 4U * npixels; j += 4)
856 const float d = fmaxf(0.0f, in[j+c] / a[c] + sigma2_plus_3_8[c]);
857 buf[j+c] = 2.0f * sqrtf(
d);
867 = { (b[0] / a[0]) * (b[0] / a[0]) + 1.f / 8.f,
868 (b[1] / a[1]) * (b[1] / a[1]) + 1.f / 8.f,
869 (b[2] / a[2]) * (b[2] / a[2]) + 1.f / 8.f,
871 const size_t npixels = (size_t)wd * ht;
872 const float sqrt_3_2 = sqrtf(3.0f / 2.0f);
874 for(
size_t j = 0; j < 4U * npixels; j += 4)
878 const float x = buf[j+c], x2 =
x *
x;
880 buf[j+c] = (
x < 0.5f)
882 : a[c] * (1.f / 4.f * x2 + 1.f / 4.f * sqrt_3_2 /
x - 11.f / 8.f / x2
883 + 5.f / 8.f * sqrt_3_2 / (
x * x2) - sigma2_plus_1_8[c]);
915static inline void precondition_v2(
const float *
const in,
float *
const buf,
const int wd,
const int ht,
919 const size_t npixels = (size_t)wd * ht;
922 (-
p[2] + 2) * sqrtf(a), 1.0f };
924 for(
size_t j = 0; j < 4U * npixels; j += 4)
928 buf[j+c] = 2.0f * powf(
MAX(in[j+c] / wb[c] + b, 0.0f), expon[c]) / denom[c];
993static inline void backtransform_v2(
float *
const buf,
const int wd,
const int ht,
const float a,
997 const size_t npixels = (size_t)wd * ht;
999 1.0f / (1.0f -
p[2] / 2.0f), 1.0f };
1000 const dt_aligned_pixel_t denom = { 4.0f / (sqrtf(a) * (2.0f -
p[0])), 4.0f / (sqrtf(a) * (2.0f -
p[1])),
1001 4.0f / (sqrtf(a) * (2.0f -
p[2])), 1.0f };
1003 for(
size_t j = 0; j < 4U * npixels; j += 4)
1007 const float x =
MAX(buf[j+c], 0.0f);
1008 const float delta =
x *
x + bias;
1009 const float z1 = (
x + sqrtf(
MAX(
delta, 0.0f))) / denom[c];
1010 buf[j+c] = wb[c] * (powf(z1, expon[c]) - b);
1022 2.0f / ((-
p[1] + 2) * sqrtf(a)),
1023 2.0f / ((-
p[2] + 2) * sqrtf(a)),
1026 for(
size_t j = 0; j < (size_t)4 * ht * wd; j += 4)
1031 tmp[c] = powf(
MAX(in[j+c] + b, 0.0f), expon[c]) * scale[c];
1033 for(
int c = 0; c < 3; c++)
1038 sum += toY0U0V0[c][
k] * tmp[
k];
1051 const dt_aligned_pixel_t bias_wb = { bias * wb[0], bias * wb[1], bias * wb[2], 0.0f };
1053 1.0f / (1.0f -
p[1] / 2.0f),
1054 1.0f / (1.0f -
p[2] / 2.0f),
1057 (sqrtf(a) * (2.0f -
p[1])) / 4.0f,
1058 (sqrtf(a) * (2.0f -
p[2])) / 4.0f,
1061 for(
size_t j = 0; j < (size_t)4 * ht * wd; j += 4)
1064 for(
int k = 0;
k < 3;
k++)
1068 rgb[
k] += toRGB[
k][c] * buf[j+c];
1073 const float x =
MAX(
rgb[c], 0.0f);
1074 const float delta =
x *
x + bias_wb[c];
1075 const float z1 = (
x + sqrtf(
MAX(
delta, 0.0f))) * scale[c];
1076 buf[j+c] = powf(z1, expon[c]) - b;
1096 wb[0] = wb[1] = wb[2] = wb[3] = wb_mean;
1097 if(
d->fix_anscombe_and_nlmeans_norm)
1099 if(wb_mean != 0.0f &&
d->wb_adaptive_anscombe)
1103 else if(wb_mean == 0.0f)
1126 const float biga = in[1][1] * in[2][2] - in[1][2] * in[2][1];
1127 const float bigb = -in[1][0] * in[2][2] + in[1][2] * in[2][0];
1128 const float bigc = in[1][0] * in[2][1] - in[1][1] * in[2][0];
1129 const float bigd = -in[0][1] * in[2][2] + in[0][2] * in[2][1];
1130 const float bige = in[0][0] * in[2][2] - in[0][2] * in[2][0];
1131 const float bigf = -in[0][0] * in[2][1] + in[0][1] * in[2][0];
1132 const float bigg = in[0][1] * in[1][2] - in[0][2] * in[1][1];
1133 const float bigh = -in[0][0] * in[1][2] + in[0][2] * in[1][0];
1134 const float bigi = in[0][0] * in[1][1] - in[0][1] * in[1][0];
1136 const float det = in[0][0] * biga + in[0][1] * bigb + in[0][2] * bigc;
1142 out[0][0] = 1.0f / det * biga;
1143 out[0][1] = 1.0f / det * bigd;
1144 out[0][2] = 1.0f / det * bigg;
1146 out[1][0] = 1.0f / det * bigb;
1147 out[1][1] = 1.0f / det * bige;
1148 out[1][2] = 1.0f / det * bigh;
1150 out[2][0] = 1.0f / det * bigc;
1151 out[2][1] = 1.0f / det * bigf;
1152 out[2][2] = 1.0f / det * bigi;
1169 float sum_invwb = 1.0f/wb[0] + 1.0f/wb[1] + 1.0f/wb[2];
1179 sum_invwb *= sqrtf(3);
1180 toY0U0V0[0][0] = sum_invwb / wb[0];
1181 toY0U0V0[0][1] = sum_invwb / wb[1];
1182 toY0U0V0[0][2] = sum_invwb / wb[2];
1183 toY0U0V0[0][3] = 0.0f;
1190 const float stddevU0 = sqrtf(0.5f * 0.5f * wb[0] * wb[0] + 0.5f * 0.5f * wb[2] * wb[2]);
1191 const float stddevV0 = sqrtf(0.25f * 0.25f * wb[0] * wb[0] + 0.5f * 0.5f * wb[1] * wb[1] + 0.25f * 0.25f * wb[2] * wb[2]);
1192 toY0U0V0[1][0] /= stddevU0;
1193 toY0U0V0[1][1] /= stddevU0;
1194 toY0U0V0[1][2] /= stddevU0;
1195 toY0U0V0[1][3] = 0.0f;
1196 toY0U0V0[2][0] /= stddevV0;
1197 toY0U0V0[2][1] /= stddevV0;
1198 toY0U0V0[2][2] /= stddevV0;
1199 toY0U0V0[2][3] = 0.0f;
1200 const gboolean is_invertible = invert_matrix(toY0U0V0, toRGB);
1204 float stddevY0 = sqrtf(1.0f / 9.0f * (wb[0] * wb[0] + wb[1] * wb[1] + wb[2] * wb[2]));
1205 toY0U0V0[0][0] = 1.0f / (3.0f * stddevY0);
1206 toY0U0V0[0][1] = 1.0f / (3.0f * stddevY0);
1207 toY0U0V0[0][2] = 1.0f / (3.0f * stddevY0);
1208 toY0U0V0[0][3] = 0.0f;
1209 invert_matrix(toY0U0V0, toRGB);
1217 const float sigma = 1.0f;
1219 const float varf = sqrtf(2.0f + 2.0f * 4.0f * 4.0f + 6.0f * 6.0f) / 16.0f;
1220 const float sigma_band = powf(varf, scale) *
sigma;
1222 const float sb2 = sigma_band * sigma_band;
1223 const dt_aligned_pixel_t var_y = { sum_y2[0] / (npixels - 1.0f), sum_y2[1] / (npixels - 1.0f),
1224 sum_y2[2] / (npixels - 1.0f), 0.0f };
1226 sqrtf(
MAX(1e-6f, var_y[2] - sb2)), 1.0f };
1241 float band_force_exp_2
1243 band_force_exp_2 *= band_force_exp_2;
1244 band_force_exp_2 *= 4;
1247 adjt[
ch] *= band_force_exp_2;
1250 band_force_exp_2 *= band_force_exp_2;
1251 band_force_exp_2 *= 4;
1252 adjt[0] *= band_force_exp_2;
1254 band_force_exp_2 *= band_force_exp_2;
1255 band_force_exp_2 *= 4;
1256 adjt[1] *= band_force_exp_2;
1258 band_force_exp_2 *= band_force_exp_2;
1259 band_force_exp_2 *= 4;
1260 adjt[2] *= band_force_exp_2;
1265 band_force_exp_2 *= band_force_exp_2;
1266 band_force_exp_2 *= 4;
1267 adjt[0] *= band_force_exp_2;
1269 band_force_exp_2 *= band_force_exp_2;
1270 band_force_exp_2 *= 4;
1271 adjt[1] *= band_force_exp_2;
1272 adjt[2] *= band_force_exp_2;
1275 thrs[
c] = adjt[
c] * sb2 / std_x[
c];
1282 const dt_iop_roi_t *
const roi_out,
const eaw_dn_decompose_t decompose,
1283 const eaw_synthesize_t synthesize)
1289#define MAX_MAX_SCALE DT_IOP_DENOISE_PROFILE_BANDS
1292 const float in_scale = fminf(roi_in->
scale, 1.0f);
1296 const float i0 = dt_log2f((supp0 - 1.0f) * .5f);
1300 const float supp = 2 * (2u << max_scale) + 1;
1302 const float supp_in = supp * (1.0f / in_scale);
1303 const float i_in = dt_log2f((supp_in - 1) * .5f) - 1.0f;
1305 const float t = 1.0f - (i_in + .5f) / i0;
1309 const int max_mult = 1u << (max_scale - 1);
1312 const float *
const restrict in = (
const float*)ivoid;
1313 float *
const restrict
out = (
float*)
ovoid;
1319 memcpy(
out, in,
sizeof(
float) * 4 * npixels);
1324 float *restrict precond = NULL;
1325 float *restrict tmp = NULL;
1339 MAX(
d->shadows + 0.1 * logf(in_scale / wb[1]), 0.0f),
1340 MAX(
d->shadows + 0.1 * logf(in_scale / wb[2]), 0.0f),
1347 { 0.5f, 0.0f, -0.5f },
1348 { 0.25f, -0.5f, 0.25f } };
1350 { 0.0f, 0.0f, 0.0f },
1351 { 0.0f, 0.0f, 0.0f } };
1356 const float compensate_strength = (
d->wavelet_color_mode ==
MODE_RGB) ? 1.0f : 2.5f;
1358 for(
size_t k = 0;
k < 3;
k++)
1361 toY0U0V0[
k][c] /= (
d->strength * compensate_strength * in_scale);
1362 toRGB[
k][c] *= (
d->strength * compensate_strength * in_scale);
1374 else if(
d->wavelet_color_mode ==
MODE_RGB)
1385 float *restrict buf1 = precond;
1386 float *restrict buf2 = tmp;
1389 memset(
out, 0,
sizeof(
float) * 4 * npixels);
1391 for(
int scale = 0; scale < max_scale; scale++)
1393 const float sigma = 1.0f;
1394 const float varf = sqrtf(2.0f + 2.0f * 4.0f * 4.0f + 6.0f * 6.0f) / 16.0f;
1395 const float sigma_band = powf(varf, scale) *
sigma;
1397 decompose(buf2, buf1, buf, sum_y2, scale, 1.0f / (sigma_band * sigma_band),
width,
height);
1403 variance_stabilizing_xform(
thrs, scale, max_scale, npixels, sum_y2,
d);
1413 for (
size_t k = 0;
k < 4U * npixels;
k++)
1420 else if(
d->wavelet_color_mode ==
MODE_RGB)
1439#if defined(HAVE_OPENCL) && !USE_NEW_IMPL_CL
1442 return (a > 0) - (a < 0);
1454 float norm = .045f / ((2 *
P + 1) * (2 *
P + 1));
1455 if(!
d->fix_anscombe_and_nlmeans_norm)
1458 norm = .015f / (2 *
P + 1);
1470 float scattering =
d->scattering;
1476 const int maxk = (K * K * K + 7.0 * K * sqrt(K)) * scattering / 6.0 + K;
1478 scattering = (maxk - K) * 6.0 / (K * K * K + 7.0 * K * sqrt(K));
1483 const int maxk = (K * K * K + 7.0 * K * sqrt(K)) * scattering / 6.0 + K;
1484 K =
MAX(
MIN(4, K), K * scale);
1485 scattering = (maxk - K) * 6.0 / (K * K * K + 7.0 * K * sqrt(K));
1495 const void *
const ivoid,
const dt_iop_roi_t *
const roi_in,
1504 p[0] =
MAX(
d->shadows + 0.1 * logf(scale / wb[0]), 0.0f);
1505 p[1] =
MAX(
d->shadows + 0.1 * logf(scale / wb[1]), 0.0f);
1506 p[2] =
MAX(
d->shadows + 0.1 * logf(scale / wb[2]), 0.0f);
1512 wb[
i] *=
d->strength * scale;
1514 aa[
i] =
d->a[1] * wb[
i];
1515 bb[
i] =
d->b[1] * wb[
i];
1526 return compensate_p;
1543 p[0] =
MAX(
d->shadows + 0.1 * logf(scale / wb[0]), 0.0f);
1544 p[1] =
MAX(
d->shadows + 0.1 * logf(scale / wb[1]), 0.0f);
1545 p[2] =
MAX(
d->shadows + 0.1 * logf(scale / wb[2]), 0.0f);
1551 wb[
i] *=
d->strength * scale;
1553 aa[
i] =
d->a[1] * wb[
i];
1554 bb[
i] =
d->b[1] * wb[
i];
1563 aa[c] =
d->a[1] * compensate_p;
1567 return compensate_p;
1592 void (*denoiser)(
const float *
const inbuf,
float *
const outbuf,
1605 const float scale = fminf(fminf(roi_in->
scale, 2.0f), 1.0f);
1606 const int P = ceilf(
d->radius * scale);
1608 const float scattering = nlmeans_scattering(pipe, &K,
d, piece, scale);
1609 const float norm = nlmeans_norm(
P,
d);
1610 const float central_pixel_weight =
d->central_pixel_weight * scale;
1617 const float compensate_p = nlmeans_precondition(
d,piece,wb,ivoid,roi_in,scale,in,aa,bb,
p);
1624 .center_weight = central_pixel_weight,
1630 denoiser(in,
ovoid,roi_in,roi_out,¶ms);
1633 nlmeans_backtransform(
d,
ovoid,roi_in,scale,compensate_p,wb,aa,bb,
p);
1648static void sum_rec(
const size_t npixels,
const float *in,
float *
out)
1656 for(
size_t i = 0;
i < npixels;
i++)
1660 out[c] += in[
i * 4 + c];
1666 const size_t npixels_first_half = npixels >> 1;
1667 const size_t npixels_second_half = npixels - npixels_first_half;
1669 sum_rec(npixels_second_half, in + 4U * npixels_first_half,
out + 4U * npixels_first_half);
1672 out[c] +=
out[4U * npixels_first_half + c];
1686 for(
size_t i = 0;
i < npixels;
i++)
1690 const float diff = in[
i * 4 + c] - mean[c];
1691 out[c] += diff * diff;
1697 const size_t npixels_first_half = npixels >> 1;
1698 const size_t npixels_second_half = npixels - npixels_first_half;
1700 variance_rec(npixels_second_half, in + 4U * npixels_first_half,
out + 4U * npixels_first_half, mean);
1703 out[c] +=
out[4U * npixels_first_half + c];
1718 memcpy(
ovoid, ivoid,
sizeof(
float) * 4 * npixels);
1734 MAX(
d->shadows - 0.1 * logf(wb[1]), 0.0f),
1735 MAX(
d->shadows - 0.1 * logf(wb[2]), 0.0f),
1751 mean[
c] =
out[
c] / npixels;
1757 var[
c] =
out[
c] / (npixels - 1);
1759 g->variance_R = var[0];
1760 g->variance_G = var[1];
1761 g->variance_B = var[2];
1763 memcpy(
ovoid, ivoid,
sizeof(
float) * 4 * npixels);
1767#if defined(HAVE_OPENCL) && !USE_NEW_IMPL_CL
1770 unsigned int current = *
state;
1771 unsigned int next = (current >=
max - 1 ? 0 : current + 1);
1779#if defined(HAVE_OPENCL)
1792 const float scale = fminf(fminf(roi_in->
scale, 2.0f), 1.0f);
1793 const int P = ceilf(
d->radius * scale);
1795 const float scattering = nlmeans_scattering(pipe, &K,
d, piece, scale);
1796 const float norm = nlmeans_norm(
P,
d);
1797 const float central_pixel_weight =
d->central_pixel_weight * scale;
1806 const int devid = pipe->
devid;
1815 const float sigma2[4] = { (bb[0] / aa[0]) * (bb[0] / aa[0]), (bb[1] / aa[1]) * (bb[1] / aa[1]),
1816 (bb[2] / aa[2]) * (bb[2] / aa[2]), 0.0f };
1845 if (err == CL_SUCCESS)
1850 .scattering = scattering,
1854 .center_weight = central_pixel_weight,
1860 .pipetype = pipe->
type,
1869 if (err == CL_SUCCESS)
1884 const float bias =
d->bias - 0.5 * logf(scale);
1900 if (err == CL_SUCCESS)
1911 const float scale = fminf(fminf(roi_in->
scale, 2.0f), 1.0f);
1912 const int P = ceilf(
d->radius * scale);
1914 const float scattering = nlmeans_scattering(pipe, &K,
d, piece, scale);
1915 const float norm = nlmeans_norm(
P,
d);
1916 const float central_pixel_weight =
d->central_pixel_weight * scale;
1924 const dt_aligned_pixel_t sigma2 = { (bb[0] / aa[0]) * (bb[0] / aa[0]), (bb[1] / aa[1]) * (bb[1] / aa[1]),
1925 (bb[2] / aa[2]) * (bb[2] / aa[2]), 0.0f };
1927 const int devid = pipe->
devid;
1935 unsigned int state = 0;
1939 if(buckets[
k] == NULL)
goto error;
1945 .cellsize =
sizeof(float), .overhead = 0,
1946 .sizex = 1u << 16, .sizey = 1 };
1949 hblocksize = hlocopt.
sizex;
1956 .cellsize =
sizeof(float), .overhead = 0,
1957 .sizex = 1, .sizey = 1u << 16 };
1960 vblocksize = vlocopt.
sizey;
1978 if(err != CL_SUCCESS)
goto error;
1991 if(err != CL_SUCCESS)
goto error;
1998 if(err != CL_SUCCESS)
goto error;
2003 for(
int kj_index = -K; kj_index <= 0; kj_index++)
2005 for(
int ki_index = -K; ki_index <= K; ki_index++)
2011 const int abs_kj = abs(kj_index);
2012 const int abs_ki = abs(ki_index);
2013 const int j = scale * ((abs_kj * abs_kj * abs_kj + 7.0 * abs_kj * sqrt(abs_ki)) *
sign(kj_index) * scattering / 6.0 + kj_index);
2014 const int i = scale * ((abs_ki * abs_ki * abs_ki + 7.0 * abs_ki * sqrt(abs_kj)) *
sign(ki_index) * scattering / 6.0 + ki_index);
2015 int q[2] = {
i, j };
2024 if(err != CL_SUCCESS)
goto error;
2029 local[0] = hblocksize;
2042 if(err != CL_SUCCESS)
goto error;
2045 sizesl[1] = bheight;
2048 local[1] = vblocksize;
2061 (
void *)¢ral_pixel_weight);
2064 if(err != CL_SUCCESS)
goto error;
2074 if(err != CL_SUCCESS)
goto error;
2088 if(err != CL_SUCCESS)
goto error;
2092 const float bias =
d->bias - 0.5 * logf(scale);
2104 if(err != CL_SUCCESS)
goto error;
2137 const float scale = fminf(roi_in->
scale, 1.0f);
2140 =
MIN(2 * (2u << (max_max_scale - 1)) + 1,
2142 const float i0 = dt_log2f((supp0 - 1.0f) * .5f);
2143 for(; max_scale < max_max_scale; max_scale++)
2146 const float supp = 2 * (2u << max_scale) + 1;
2148 const float supp_in = supp * (1.0f / scale);
2149 const float i_in = dt_log2f((supp_in - 1) * .5f) - 1.0f;
2151 const float t = 1.0f - (i_in + .5f) / i0;
2155 const int devid = pipe->
devid;
2161 cl_mem dev_tmp = NULL;
2162 cl_mem dev_buf1 = NULL;
2163 cl_mem dev_buf2 = NULL;
2164 cl_mem dev_m = NULL;
2165 cl_mem dev_r = NULL;
2166 cl_mem dev_filter = NULL;
2167 cl_mem *dev_detail = calloc(max_max_scale,
sizeof(cl_mem));
2168 float *sumsum = NULL;
2175 size_t origin[] = { 0, 0, 0 };
2178 if(err != CL_SUCCESS)
goto error;
2185 .cellsize = 4 *
sizeof(float), .overhead = 0,
2186 .sizex = 1u << 4, .sizey = 1u << 4 };
2194 const int bufsize = (bwidth / flocopt.
sizex) * (bheight / flocopt.
sizey);
2198 .cellsize = 4 *
sizeof(float), .overhead = 0,
2199 .sizex = 1u << 16, .sizey = 1 };
2219 float m[] = { 0.0625f, 0.25f, 0.375f, 0.25f, 0.0625f };
2221 for(
int j = 0; j < 5; j++)
2222 for(
int i = 0;
i < 5;
i++) mm[j][
i] =
m[
i] *
m[j];
2227 for(
int k = 0;
k < max_scale;
k++)
2230 if(dev_detail[
k] == NULL)
goto error;
2240 MAX(
d->shadows + 0.1 * logf(scale / wb[1]), 0.0f),
2241 MAX(
d->shadows + 0.1 * logf(scale / wb[2]), 0.0f), 1.0f};
2245 { 0.5f, 0.0f, -0.5f },
2246 { 0.25f, -0.5f, 0.25f } };
2248 { 0.0f, 0.0f, 0.0f },
2249 { 0.0f, 0.0f, 0.0f } };
2254 const float compensate_strength = (
d->wavelet_color_mode ==
MODE_RGB) ? 1.0f : 2.5f;
2259 for(
size_t k = 0;
k < 3;
k++)
2260 for(
size_t c = 0; c < 3; c++)
2263 toRGB[3*
k+c] = toRGB_tmp[
k][c] *
d->strength * compensate_strength * scale;
2264 toY0U0V0[3*
k+c] = toY0U0V0_tmp[
k][c] / (
d->strength * compensate_strength * scale);
2272 const dt_aligned_pixel_t sigma2 = { (bb[0] / aa[0]) * (bb[0] / aa[0]), (bb[1] / aa[1]) * (bb[1] / aa[1]),
2273 (bb[2] / aa[2]) * (bb[2] / aa[2]), 0.0f };
2279 aa[c] =
d->a[1] * compensate_p;
2295 if(err != CL_SUCCESS)
goto error;
2297 else if(
d->wavelet_color_mode ==
MODE_RGB)
2308 if(err != CL_SUCCESS)
goto error;
2312 cl_mem dev_Y0U0V0 = NULL;
2326 if(err != CL_SUCCESS)
goto error;
2339 for(
int s = 0; s < max_scale; s++)
2341 const float sigma = 1.0f;
2342 const float varf = sqrtf(2.0f + 2.0f * 4.0f * 4.0f + 6.0f * 6.0f) / 16.0f;
2343 const float sigma_band = powf(varf, s) *
sigma;
2344 const float inv_sigma2 = 1.0f / (sigma_band * sigma_band);
2349 (
void *)&dev_detail[s]);
2355 (
void *)&inv_sigma2);
2357 (
void *)&dev_filter);
2359 if(err != CL_SUCCESS)
goto error;
2362 cl_mem dev_buf3 = dev_buf2;
2363 dev_buf2 = dev_buf1;
2364 dev_buf1 = dev_buf3;
2368 for(
int s = max_scale - 1; s >= 0; s--)
2371 const float sigma = 1.0f;
2373 const float varf = sqrtf(2.0f + 2.0f * 4.0f * 4.0f + 6.0f * 6.0f) / 16.0f;
2374 const float sigma_band = powf(varf, s) *
sigma;
2383 lsizes[1] = bheight;
2385 llocal[0] = flocopt.
sizex;
2386 llocal[1] = flocopt.
sizey;
2394 sizeof(
float) * 4 * flocopt.
sizex * flocopt.
sizey, NULL);
2397 if(err != CL_SUCCESS)
goto error;
2400 lsizes[0] = (size_t)reducesize * slocopt.
sizex;
2403 llocal[0] = slocopt.
sizex;
2413 if(err != CL_SUCCESS)
goto error;
2416 sizeof(
float) * 4 * reducesize, CL_TRUE);
2417 if(err != CL_SUCCESS)
2420 for(
int k = 0;
k < reducesize;
k++)
2424 sum_y2[c] += sumsum[4 *
k + c];
2428 const float sb2 = sigma_band * sigma_band;
2429 const dt_aligned_pixel_t var_y = { sum_y2[0] / (npixels - 1.0f), sum_y2[1] / (npixels - 1.0f),
2430 sum_y2[2] / (npixels - 1.0f), 0.0f };
2432 sqrtf(
MAX(1e-6f, var_y[2] - sb2)), 1.0f };
2448 band_force_exp_2 *= band_force_exp_2;
2449 band_force_exp_2 *= 4;
2452 adjt[
ch] *= band_force_exp_2;
2455 band_force_exp_2 *= band_force_exp_2;
2456 band_force_exp_2 *= 4;
2457 adjt[0] *= band_force_exp_2;
2459 band_force_exp_2 *= band_force_exp_2;
2460 band_force_exp_2 *= 4;
2461 adjt[1] *= band_force_exp_2;
2463 band_force_exp_2 *= band_force_exp_2;
2464 band_force_exp_2 *= 4;
2465 adjt[2] *= band_force_exp_2;
2470 band_force_exp_2 *= band_force_exp_2;
2471 band_force_exp_2 *= 4;
2472 adjt[0] *= band_force_exp_2;
2474 band_force_exp_2 *= band_force_exp_2;
2475 band_force_exp_2 *= 4;
2476 adjt[1] *= band_force_exp_2;
2477 adjt[2] *= band_force_exp_2;
2481 adjt[2] * sb2 / std_x[2], 0.0f };
2489 (
void *)&dev_detail[s]);
2506 if(err != CL_SUCCESS)
goto error;
2509 cl_mem dev_buf3 = dev_buf2;
2510 dev_buf2 = dev_buf1;
2511 dev_buf1 = dev_buf3;
2516 if(dev_buf1 != dev_tmp)
2518 size_t origin[] = { 0, 0, 0 };
2521 if(err != CL_SUCCESS)
goto error;
2533 if(err != CL_SUCCESS)
goto error;
2535 else if(
d->wavelet_color_mode ==
MODE_RGB)
2537 const float bias =
d->bias - 0.5 * logf(scale);
2548 if(err != CL_SUCCESS)
goto error;
2552 cl_mem dev_RGB = NULL;
2556 const float bias =
d->bias - 0.5 * logf(scale);
2569 if(err != CL_SUCCESS)
goto error;
2582 for(
int k = 0;
k < max_scale;
k++)
2593 for(
int k = 0;
k < max_scale;
k++)
2631 err = process_nlmeans(pipe, piece, ivoid,
ovoid, roi_in, roi_out);
2635 err = process_variance(self, pipe, piece, ivoid,
ovoid, roi_in, roi_out);
2641 return MIN((
unsigned)(1.0f + a * 15000.0f + a * a * 300000.0f), 8);
2646 return MIN(3000.0f * a, 1.0f);
2651 return MIN(
MAX(0.1f - 0.1 * logf(a), 0.7f), 1.8f);
2656 return -
MAX(5 + 0.5 * logf(a), 0.0);
2691 g_strlcpy(
name, _(
g->interpolated.name),
sizeof(
name));
2693 const int iso =
module->dev->image_storage.exif_iso;
2695 for(GList *iter =
g->profiles; iter; iter = g_list_next(iter))
2699 if(current->
iso == iso)
2701 g->interpolated = *current;
2703 g->interpolated.
a[0] = -1.0f;
2704 snprintf(
name,
sizeof(
name), _(
"found match for ISO %d"), iso);
2707 if(last && last->
iso < iso && current->
iso > iso)
2709 g->interpolated.iso = iso;
2712 g->interpolated.a[0] = -1.0f;
2713 snprintf(
name,
sizeof(
name), _(
"interpolated from ISO %d and %d"), last->
iso, current->
iso);
2720 for(GList *iter =
g->profiles; iter; iter = g_list_next(iter))
2728 const float a =
g->interpolated.a[1];
2741 for(
int k = 0;
k < 3;
k++)
2743 d->a[
k] =
g->interpolated.a[
k];
2744 d->b[
k] =
g->interpolated.b[
k];
2751 const int program = 11;
2802 for(GList *iter = profiles; iter; iter = g_list_next(iter))
2805 if(current->
iso == iso)
2807 interpolated = *current;
2810 if(last && last->
iso < iso && current->
iso > iso)
2812 interpolated.
iso = iso;
2820 return interpolated;
2830 d->nbhood =
p->nbhood;
2831 d->central_pixel_weight =
p->central_pixel_weight;
2832 d->strength =
p->strength;
2833 d->overshooting =
p->overshooting;
2834 for(
int i = 0;
i < 3;
i++)
2840 d->wavelet_color_mode =
p->wavelet_color_mode;
2849 for(
int k = 0;
k < 3;
k++)
2851 d->a[
k] = interpolated.
a[
k];
2852 d->b[
k] = interpolated.
b[
k];
2858 const float gain =
p->overshooting;
2866 d->radius =
p->radius;
2867 d->scattering =
p->scattering;
2868 d->shadows =
p->shadows;
2882 d->wb_adaptive_anscombe =
p->wb_adaptive_anscombe;
2883 d->fix_anscombe_and_nlmeans_norm =
p->fix_anscombe_and_nlmeans_norm;
2884 d->use_new_vst =
p->use_new_vst;
2893 piece->
data = (
void *)
d;
2918 for(
int k = 0;
k < 3;
k++)
2920 p->
a[
k] = profile->
a[
k];
2921 p->b[
k] = profile->
b[
k];
2935 gtk_widget_hide(
g->box_wavelets);
2936 gtk_widget_hide(
g->box_variance);
2937 gtk_widget_show_all(
g->box_nlm);
2941 gtk_widget_hide(
g->box_wavelets);
2942 gtk_widget_hide(
g->box_variance);
2943 gtk_widget_show_all(
g->box_nlm);
2944 gtk_widget_set_visible(
g->radius,
FALSE);
2945 gtk_widget_set_visible(
g->nbhood,
FALSE);
2946 gtk_widget_set_visible(
g->scattering,
FALSE);
2950 gtk_widget_hide(
g->box_nlm);
2951 gtk_widget_hide(
g->box_variance);
2952 gtk_widget_show_all(
g->box_wavelets);
2953 gtk_widget_set_visible(GTK_WIDGET(
g->wavelet_color_mode),
p->use_new_vst);
2954 gtk_widget_set_visible(GTK_WIDGET(
g->channel_tabs),
p->use_new_vst && (
p->wavelet_color_mode ==
MODE_RGB));
2955 gtk_widget_set_visible(GTK_WIDGET(
g->channel_tabs_Y0U0V0),
p->use_new_vst && (
p->wavelet_color_mode ==
MODE_Y0U0V0));
2959 gtk_widget_hide(
g->box_nlm);
2960 gtk_widget_hide(
g->box_variance);
2961 gtk_widget_show_all(
g->box_wavelets);
2962 gtk_widget_set_visible(GTK_WIDGET(
g->wavelet_color_mode),
p->use_new_vst);
2963 gtk_widget_set_visible(GTK_WIDGET(
g->channel_tabs),
p->use_new_vst && (
p->wavelet_color_mode ==
MODE_RGB));
2964 gtk_widget_set_visible(GTK_WIDGET(
g->channel_tabs_Y0U0V0),
p->use_new_vst && (
p->wavelet_color_mode ==
MODE_Y0U0V0));
2968 gtk_widget_hide(
g->box_wavelets);
2969 gtk_widget_hide(
g->box_nlm);
2970 gtk_widget_show_all(
g->box_variance);
2974 gtk_widget_set_visible(
g->shadows,
p->use_new_vst && !auto_mode);
2975 gtk_widget_set_visible(
g->bias,
p->use_new_vst && !auto_mode);
2976 gtk_widget_set_visible(
g->overshooting, auto_mode);
2985 if(w ==
g->wavelet_color_mode)
2987 gtk_widget_set_visible(GTK_WIDGET(
g->channel_tabs), (
p->wavelet_color_mode ==
MODE_RGB));
2988 gtk_widget_set_visible(GTK_WIDGET(
g->channel_tabs_Y0U0V0), (
p->wavelet_color_mode ==
MODE_Y0U0V0));
2994 else if(w ==
g->overshooting)
2996 const float gain =
p->overshooting;
3001 a = interpolated.
a[1];
3007 gtk_widget_set_visible(
g->radius,
TRUE);
3008 gtk_widget_set_visible(
g->scattering,
TRUE);
3011 gtk_widget_set_visible(
g->radius,
FALSE);
3012 gtk_widget_set_visible(
g->scattering,
FALSE);
3018 gtk_widget_show_all(
g->box_nlm);
3021 gtk_widget_hide(
g->box_nlm);
3023 gtk_widget_set_visible(
g->shadows,
TRUE);
3024 gtk_widget_set_visible(
g->bias,
TRUE);
3027 gtk_widget_set_visible(
g->shadows,
FALSE);
3028 gtk_widget_set_visible(
g->bias,
FALSE);
3030 else if(w ==
g->use_new_vst)
3033 gtk_widget_set_visible(
g->shadows,
p->use_new_vst && !auto_mode);
3034 gtk_widget_set_visible(
g->bias,
p->use_new_vst && !auto_mode);
3035 gtk_widget_set_visible(
g->wavelet_color_mode,
p->use_new_vst);
3047 unsigned combobox_index = 0;
3052 gtk_widget_hide(
g->box_wavelets);
3053 gtk_widget_hide(
g->box_variance);
3054 gtk_widget_show_all(
g->box_nlm);
3058 gtk_widget_hide(
g->box_wavelets);
3059 gtk_widget_hide(
g->box_variance);
3060 gtk_widget_show_all(
g->box_nlm);
3061 gtk_widget_set_visible(
g->radius,
FALSE);
3062 gtk_widget_set_visible(
g->nbhood,
FALSE);
3063 gtk_widget_set_visible(
g->scattering,
FALSE);
3067 gtk_widget_hide(
g->box_nlm);
3068 gtk_widget_hide(
g->box_variance);
3069 gtk_widget_show_all(
g->box_wavelets);
3073 gtk_widget_hide(
g->box_nlm);
3074 gtk_widget_hide(
g->box_variance);
3075 gtk_widget_show_all(
g->box_wavelets);
3079 gtk_widget_hide(
g->box_wavelets);
3080 gtk_widget_hide(
g->box_nlm);
3081 gtk_widget_show_all(
g->box_variance);
3092 a = interpolated.
a[1];
3096 const float gain =
p->overshooting;
3110 for(GList *iter =
g->profiles; iter; iter = g_list_next(iter),
i++)
3113 if(!memcmp(profile->
a,
p->a,
sizeof(
float) * 3)
3114 && !memcmp(profile->
b,
p->b,
sizeof(
float) * 3))
3121 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(
g->wb_adaptive_anscombe),
p->wb_adaptive_anscombe);
3122 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(
g->fix_anscombe_and_nlmeans_norm),
p->fix_anscombe_and_nlmeans_norm);
3123 gtk_widget_set_visible(
g->fix_anscombe_and_nlmeans_norm, !
p->fix_anscombe_and_nlmeans_norm);
3124 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(
g->use_new_vst),
p->use_new_vst);
3125 gtk_widget_set_visible(
g->use_new_vst, !
p->use_new_vst);
3128 gtk_widget_set_visible(
g->overshooting, auto_mode);
3129 gtk_widget_set_visible(
g->wavelet_color_mode,
p->use_new_vst && wavelet_mode);
3130 gtk_widget_set_visible(
g->shadows,
p->use_new_vst && !auto_mode);
3131 gtk_widget_set_visible(
g->bias,
p->use_new_vst && !auto_mode);
3132 gtk_widget_set_visible(GTK_WIDGET(
g->channel_tabs), (
p->wavelet_color_mode ==
MODE_RGB));
3133 gtk_widget_set_visible(GTK_WIDGET(
g->channel_tabs_Y0U0V0), (
p->wavelet_color_mode ==
MODE_Y0U0V0));
3142 gtk_notebook_set_current_page(GTK_NOTEBOOK(
g->channel_tabs),
g->channel);
3158 gtk_notebook_set_current_page(GTK_NOTEBOOK(
g->channel_tabs),
g->channel);
3160 gtk_widget_set_visible(
g->fix_anscombe_and_nlmeans_norm, !
p->fix_anscombe_and_nlmeans_norm);
3161 gtk_widget_set_visible(
g->use_new_vst, !
p->use_new_vst);
3165 const double mouse_y,
const float rad)
3169 const float f = expf(-(mouse_x -
p->x[
ch][
k]) * (mouse_x -
p->x[
ch][
k]) / (rad * rad));
3170 p->y[
ch][
k] = (1 -
f) *
p->y[
ch][
k] +
f * mouse_y;
3181 if(!isnan(c->variance_R))
3183 gchar *str = g_strdup_printf(
"%.2f", c->variance_R);
3185 gtk_label_set_text(c->label_var_R, str);
3189 if(!isnan(c->variance_G))
3191 gchar *str = g_strdup_printf(
"%.2f", c->variance_G);
3193 gtk_label_set_text(c->label_var_G, str);
3197 if(!isnan(c->variance_B))
3199 gchar *str = g_strdup_printf(
"%.2f", c->variance_B);
3201 gtk_label_set_text(c->label_var_B, str);
3214 int ch = (int)c->channel;
3222 GtkAllocation allocation;
3223 gtk_widget_get_allocation(widget, &allocation);
3224 int width = allocation.width,
height = allocation.height;
3226 cairo_t *cr = cairo_create(cst);
3227 cairo_set_source_rgb(cr, .2, .2, .2);
3231 cairo_translate(cr, inset, inset);
3236 cairo_set_source_rgb(cr, .1, .1, .1);
3240 cairo_set_source_rgb(cr, .3, .3, .3);
3246 cairo_set_source_rgb(cr, .1, .1, .1);
3249 if(c->mouse_y > 0 || c->dragging)
3275 cairo_translate(cr, 0,
height);
3277 cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
3291 cairo_set_source_rgba(cr, .7, .7, .7, alpha);
3294 cairo_set_source_rgba(cr, .7, .1, .1, alpha);
3297 cairo_set_source_rgba(cr, .1, .7, .1, alpha);
3300 cairo_set_source_rgba(cr, .1, .1, .7, alpha);
3303 cairo_set_source_rgba(cr, 7, .7, .7, 0.0f);
3312 cairo_set_source_rgba(cr, .7, .7, .7, alpha);
3315 cairo_set_source_rgba(cr, .8, .4, .0, alpha);
3318 cairo_set_source_rgba(cr, .7, .7, .7, 0.0f);
3338 cairo_set_source_rgb(cr, 0.7, 0.7, 0.7);
3349 if(c->mouse_y > 0 || c->dragging)
3352 cairo_set_source_rgba(cr, .7, .7, .7, .6);
3353 cairo_move_to(cr, 0, -
height * c->draw_min_ys[0]);
3358 cairo_close_path(cr);
3361 cairo_set_source_rgba(cr, .9, .9, .9, .5);
3364 const float f =
k - pos;
3366 float ht = -
height * (
f * c->draw_ys[
k] + (1 -
f) * c->draw_ys[
k + 1]);
3367 cairo_arc(cr, c->mouse_x *
width, ht, c->mouse_radius *
width, 0, 2. *
M_PI);
3373 cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
3376 PangoLayout *layout;
3379 pango_font_description_set_weight(desc, PANGO_WEIGHT_BOLD);
3380 pango_font_description_set_absolute_size(desc, (.08 *
height) * PANGO_SCALE);
3381 layout = pango_cairo_create_layout(cr);
3382 pango_layout_set_font_description(layout, desc);
3383 cairo_set_source_rgb(cr, .1, .1, .1);
3385 pango_layout_set_text(layout, _(
"coarse"), -1);
3386 pango_layout_get_pixel_extents(layout, &ink, NULL);
3387 cairo_move_to(cr, .02 *
width - ink.y, .5 * (
height + ink.width));
3389 cairo_rotate(cr, -
M_PI * .5f);
3390 pango_cairo_show_layout(cr, layout);
3393 pango_layout_set_text(layout, _(
"fine"), -1);
3394 pango_layout_get_pixel_extents(layout, &ink, NULL);
3395 cairo_move_to(cr, .98 *
width - ink.height, .5 * (
height + ink.width));
3397 cairo_rotate(cr, -
M_PI * .5f);
3398 pango_cairo_show_layout(cr, layout);
3402 pango_layout_set_text(layout, _(
"smooth"), -1);
3403 pango_layout_get_pixel_extents(layout, &ink, NULL);
3404 cairo_move_to(cr, .5 * (
width - ink.width), .08 *
height - ink.height);
3405 pango_cairo_show_layout(cr, layout);
3407 pango_layout_set_text(layout, _(
"noisy"), -1);
3408 pango_layout_get_pixel_extents(layout, &ink, NULL);
3409 cairo_move_to(cr, .5 * (
width - ink.width), .97 *
height - ink.height);
3410 pango_cairo_show_layout(cr, layout);
3412 pango_font_description_free(desc);
3413 g_object_unref(layout);
3415 cairo_set_source_surface(crf, cst, 0, 0);
3417 cairo_surface_destroy(cst);
3427 GtkAllocation allocation;
3428 gtk_widget_get_allocation(widget, &allocation);
3429 int height = allocation.height - 2 * inset,
width = allocation.width - 2 * inset;
3430 if(!c->dragging) c->mouse_x = CLAMP(event->x - inset, 0,
width) / (float)
width;
3431 c->mouse_y = 1.0 - CLAMP(event->y - inset, 0,
height) / (float)
height;
3434 *
p = c->drag_params;
3445 gtk_widget_queue_draw(widget);
3453 const int ch = c->channel;
3454 if(event->button == 1 && event->type == GDK_2BUTTON_PRESS)
3466 gtk_widget_queue_draw(self->
widget);
3468 else if(event->button == 1)
3472 GtkAllocation allocation;
3473 gtk_widget_get_allocation(widget, &allocation);
3474 int height = allocation.height - 2 * inset,
width = allocation.width - 2 * inset;
3477 c->mouse_pick -= 1.0 - CLAMP(event->y - inset, 0,
height) / (float)
height;
3486 if(event->button == 1)
3500 if(!c->dragging) c->mouse_y = -1.0;
3501 gtk_widget_queue_draw(widget);
3514 gtk_widget_queue_draw(widget);
3530 gtk_widget_queue_draw(self->
widget);
3559 g->channel_tabs = GTK_NOTEBOOK(gtk_notebook_new());
3565 gtk_box_pack_start(GTK_BOX(
g->box_wavelets), GTK_WIDGET(
g->channel_tabs),
FALSE,
FALSE, 0);
3567 g->channel_tabs_Y0U0V0 = GTK_NOTEBOOK(gtk_notebook_new());
3571 gtk_box_pack_start(GTK_BOX(
g->box_wavelets), GTK_WIDGET(
g->channel_tabs_Y0U0V0),
FALSE,
FALSE, 0);
3573 const int ch = (int)
g->channel;
3581 g->mouse_x =
g->mouse_y =
g->mouse_pick = -1.0;
3586 g->area = GTK_DRAWING_AREA(gtk_drawing_area_new());
3587 gtk_widget_set_hexpand(GTK_WIDGET(
g->area),
TRUE);
3589 gtk_widget_add_events(GTK_WIDGET(
g->area), GDK_POINTER_MOTION_MASK
3590 | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK
3598 gtk_box_pack_start(GTK_BOX(
g->box_wavelets),
3600 "plugins/darkroom/denoiseprofile/graphheight", 280, 100),
3606 "uniform image if you want to\n"
3607 "estimate the noise variance.")));
3608 gtk_box_pack_start(GTK_BOX(
g->box_variance), GTK_WIDGET(
g->label_var),
TRUE,
TRUE, 0);
3610 GtkBox *hboxR = GTK_BOX(gtk_box_new(GTK_ORIENTATION_HORIZONTAL,
DT_GUI_BOX_SPACING));
3612 gtk_box_pack_start(GTK_BOX(hboxR), GTK_WIDGET(labelR),
FALSE,
FALSE, 0);
3614 gtk_widget_set_tooltip_text(GTK_WIDGET(
g->label_var_R), _(
"variance computed on the red channel"));
3615 gtk_box_pack_start(GTK_BOX(hboxR), GTK_WIDGET(
g->label_var_R),
FALSE,
FALSE, 0);
3616 gtk_box_pack_start(GTK_BOX(
g->box_variance), GTK_WIDGET(hboxR),
TRUE,
TRUE, 0);
3618 GtkBox *hboxG = GTK_BOX(gtk_box_new(GTK_ORIENTATION_HORIZONTAL,
DT_GUI_BOX_SPACING));
3620 gtk_box_pack_start(GTK_BOX(hboxG), GTK_WIDGET(labelG),
FALSE,
FALSE, 0);
3622 gtk_widget_set_tooltip_text(GTK_WIDGET(
g->label_var_G), _(
"variance computed on the green channel"));
3623 gtk_box_pack_start(GTK_BOX(hboxG), GTK_WIDGET(
g->label_var_G),
FALSE,
FALSE, 0);
3624 gtk_box_pack_start(GTK_BOX(
g->box_variance), GTK_WIDGET(hboxG),
TRUE,
TRUE, 0);
3626 GtkBox *hboxB = GTK_BOX(gtk_box_new(GTK_ORIENTATION_HORIZONTAL,
DT_GUI_BOX_SPACING));
3628 gtk_box_pack_start(GTK_BOX(hboxB), GTK_WIDGET(labelB),
FALSE,
FALSE, 0);
3630 gtk_widget_set_tooltip_text(GTK_WIDGET(
g->label_var_B), _(
"variance computed on the blue channel"));
3631 gtk_box_pack_start(GTK_BOX(hboxB), GTK_WIDGET(
g->label_var_B),
FALSE,
FALSE, 0);
3632 gtk_box_pack_start(GTK_BOX(
g->box_variance), GTK_WIDGET(hboxB),
TRUE,
TRUE, 0);
3641 g_signal_connect(G_OBJECT(
g->profile),
"value-changed", G_CALLBACK(
profile_callback), self);
3652 const gboolean compute_variance =
dt_conf_get_bool(
"plugins/darkroom/denoiseprofile/show_compute_variance_mode");
3654 g_signal_connect(G_OBJECT(
g->mode),
"value-changed", G_CALLBACK(
mode_callback), self);
3658 gtk_box_pack_start(GTK_BOX(self->
widget),
g->box_wavelets,
TRUE,
TRUE, 0);
3669 gtk_box_pack_start(GTK_BOX(self->
widget),
g->box_variance,
TRUE,
TRUE, 0);
3675 gtk_widget_set_tooltip_text(
g->wb_adaptive_anscombe, _(
"adapt denoising according to the\n"
3676 "white balance coefficients.\n"
3677 "should be enabled on a first instance\n"
3678 "for better denoising.\n"
3679 "should be disabled if an earlier instance\n"
3680 "has been used with a color blending mode."));
3681 gtk_widget_set_tooltip_text(
g->fix_anscombe_and_nlmeans_norm, _(
"fix bugs in anscombe transform resulting\n"
3682 "in undersmoothing of the green channel in\n"
3683 "wavelets mode, combined with a bad handling\n"
3684 "of white balance coefficients, and a bug in\n"
3685 "non local means normalization resulting in\n"
3686 "undersmoothing when patch size was increased.\n"
3687 "enabling this option will change the denoising\n"
3688 "you get. once enabled, you won't be able to\n"
3689 "return back to old algorithm."));
3690 gtk_widget_set_tooltip_text(
g->profile, _(
"profile used for variance stabilization"));
3691 gtk_widget_set_tooltip_text(
g->mode, _(
"method used in the denoising core.\n"
3692 "non-local means works best for `lightness' blending,\n"
3693 "wavelets work best for `color' blending"));
3694 gtk_widget_set_tooltip_text(
g->wavelet_color_mode, _(
"color representation used within the algorithm.\n"
3695 "RGB keeps the RGB channels separated,\n"
3696 "while Y0U0V0 combine the channels to\n"
3697 "denoise chroma and luma separately."));
3698 gtk_widget_set_tooltip_text(
g->radius, _(
"radius of the patches to match.\n"
3699 "increase for more sharpness on strong edges, and better denoising of smooth areas.\n"
3700 "if details are oversmoothed, reduce this value or increase the central pixel weight slider."));
3701 gtk_widget_set_tooltip_text(
g->nbhood, _(
"emergency use only: radius of the neighbourhood to search patches in. "
3702 "increase for better denoising performance, but watch the long runtimes! "
3703 "large radii can be very slow. you have been warned"));
3704 gtk_widget_set_tooltip_text(
g->scattering, _(
"scattering of the neighbourhood to search patches in.\n"
3705 "increase for better coarse-grain noise reduction.\n"
3706 "does not affect execution time."));
3707 gtk_widget_set_tooltip_text(
g->central_pixel_weight, _(
"increase the weight of the central pixel\n"
3708 "of the patch in the patch comparison.\n"
3709 "useful to recover details when patch size\n"
3711 gtk_widget_set_tooltip_text(
g->strength, _(
"finetune denoising strength"));
3712 gtk_widget_set_tooltip_text(
g->overshooting, _(
"controls the way parameters are autoset\n"
3713 "increase if shadows are not denoised enough\n"
3714 "or if chroma noise remains.\n"
3715 "this can happen if your picture is underexposed."));
3716 gtk_widget_set_tooltip_text(
g->shadows, _(
"finetune shadows denoising.\n"
3717 "decrease to denoise more aggressively\n"
3718 "dark areas of the image."));
3719 gtk_widget_set_tooltip_text(
g->bias, _(
"correct color cast in shadows.\n"
3720 "decrease if shadows are too purple.\n"
3721 "increase if shadows are too green."));
3722 gtk_widget_set_tooltip_text(
g->use_new_vst, _(
"upgrade the variance stabilizing algorithm.\n"
3723 "new algorithm extends the current one.\n"
3724 "it is more flexible but could give small\n"
3725 "differences in the images already processed."));
static void error(char *msg)
void dt_bauhaus_slider_set_soft_range(GtkWidget *widget, float soft_min, float soft_max)
void dt_bauhaus_slider_set_digits(GtkWidget *widget, int val)
void dt_bauhaus_combobox_clear(GtkWidget *widget)
void dt_bauhaus_slider_set_default(GtkWidget *widget, float def)
int dt_bauhaus_combobox_get(GtkWidget *widget)
void dt_bauhaus_slider_set_soft_max(GtkWidget *widget, float val)
int dt_bauhaus_combobox_length(GtkWidget *widget)
void dt_bauhaus_slider_set(GtkWidget *widget, float pos)
void dt_bauhaus_combobox_set(GtkWidget *widget, const int pos)
void dt_bauhaus_widget_set_label(GtkWidget *widget, const char *label)
GtkWidget * dt_bauhaus_combobox_new(dt_bauhaus_t *bh, dt_gui_module_t *self)
void dt_bauhaus_combobox_add(GtkWidget *widget, const char *text)
@ DEVELOP_BLEND_CS_RGB_SCENE
static const dt_aligned_pixel_simd_t const dt_adaptation_t const float p
static dt_aligned_pixel_t rgb
const dt_aligned_pixel_t f
const dt_colormatrix_t dt_aligned_pixel_t out
typedef void((*dt_cache_allocate_t)(void *userdata, dt_cache_entry_t *entry))
int dt_conf_get_bool(const char *name)
void dt_print(dt_debug_thread_t thread, const char *msg,...)
#define dt_free_align(ptr)
static void * dt_calloc_align(size_t size)
#define __OMP_SIMD__(...)
#define for_each_channel(_var,...)
float dt_aligned_pixel_simd_t __attribute__((vector_size(16), aligned(16)))
Enable aggressive floating-point arithmetic optimizations, in denormals handling. Set through user pr...
#define dt_pixelpipe_cache_alloc_align(size, pipe)
static const dt_aligned_pixel_simd_t sign
#define DT_MODULE_INTROSPECTION(MODVER, PARAMSTYPE)
#define dt_pixelpipe_cache_free_align(mem)
#define __DT_CLONE_TARGETS__
#define __OMP_PARALLEL_FOR__(...)
#define IS_NULL_PTR(p)
C is way too permissive with !=, == and if(var) checks, which can mean too many things depending on w...
#define DT_CACHELINE_BYTES
static int bucket_next(unsigned int *state, unsigned int max)
#define DT_IOP_DENOISE_PROFILE_BANDS
dt_iop_denoiseprofile_channel_t
@ DT_DENOISE_PROFILE_NONE
@ DT_DENOISE_PROFILE_U0V0
void init(dt_iop_module_t *module)
static __DT_CLONE_TARGETS__ void set_up_conversion_matrices(dt_colormatrix_t toY0U0V0, dt_colormatrix_t toRGB, const dt_aligned_pixel_t wb)
const char ** description(struct dt_iop_module_t *self)
static float infer_bias_from_profile(const float a)
void gui_reset(dt_iop_module_t *self)
#define DT_DENOISE_PROFILE_NONE_V9
static void profile_callback(GtkWidget *w, dt_iop_module_t *self)
void reload_defaults(dt_iop_module_t *module)
static __DT_CLONE_TARGETS__ void compute_wb_factors(dt_aligned_pixel_t wb, const dt_iop_denoiseprofile_data_t *const d, const dt_dev_pixelpipe_iop_t *const piece, const dt_aligned_pixel_t weights)
static __DT_CLONE_TARGETS__ void backtransform_v2(float *const buf, const int wd, const int ht, const float a, const dt_aligned_pixel_t p, const float b, const float bias, const dt_aligned_pixel_t wb)
void commit_params(struct dt_iop_module_t *self, dt_iop_params_t *params, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
static int process_nlmeans_cl(struct dt_iop_module_t *self, const dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece, cl_mem dev_in, cl_mem dev_out, const dt_iop_roi_t *const roi_in, const dt_iop_roi_t *const roi_out)
static void dt_iop_denoiseprofile_get_params(dt_iop_denoiseprofile_params_t *p, const int ch, const double mouse_x, const double mouse_y, const float rad)
void gui_update(dt_iop_module_t *self)
static __DT_CLONE_TARGETS__ void backtransform(float *const buf, const int wd, const int ht, const dt_aligned_pixel_t a, const dt_aligned_pixel_t b)
static int process_wavelets_cl(struct dt_iop_module_t *self, const dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece, cl_mem dev_in, cl_mem dev_out, const dt_iop_roi_t *const roi_in, const dt_iop_roi_t *const roi_out)
void init_pipe(struct dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
static dt_noiseprofile_t dt_iop_denoiseprofile_get_auto_profile(dt_iop_module_t *self)
#define debug_dump_PFM(p, n, b, w, h, s)
static gboolean denoiseprofile_button_release(GtkWidget *widget, GdkEventButton *event, gpointer user_data)
#define DT_IOP_DENOISE_PROFILE_INSET
static float nlmeans_precondition_cl(const dt_iop_denoiseprofile_data_t *const d, const dt_dev_pixelpipe_iop_t *const piece, dt_aligned_pixel_t wb, float scale, dt_aligned_pixel_t aa, dt_aligned_pixel_t bb, dt_aligned_pixel_t p)
void gui_init(dt_iop_module_t *self)
void gui_changed(dt_iop_module_t *self, GtkWidget *w, void *previous)
#define DT_IOP_DENOISE_PROFILE_RES
dt_iop_denoiseprofile_wavelet_mode_t
void tiling_callback(struct dt_iop_module_t *self, const struct dt_dev_pixelpipe_t *pipe, const struct dt_dev_pixelpipe_iop_t *piece, struct dt_develop_tiling_t *tiling)
static __DT_CLONE_TARGETS__ void backtransform_Y0U0V0(float *const buf, const int wd, const int ht, const float a, const dt_aligned_pixel_t p, const float b, const float bias, const dt_aligned_pixel_t wb, const dt_colormatrix_t toRGB)
void gui_cleanup(dt_iop_module_t *self)
static gboolean denoiseprofile_draw_variance(GtkWidget *widget, cairo_t *crf, gpointer user_data)
static float infer_scattering_from_profile(const float a)
void cleanup_global(dt_iop_module_so_t *module)
int default_colorspace(dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece)
static float infer_shadows_from_profile(const float a)
static __DT_CLONE_TARGETS__ int process_wavelets(struct dt_iop_module_t *self, const dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece, const void *const ivoid, void *const ovoid, const dt_iop_roi_t *const roi_in, const dt_iop_roi_t *const roi_out, const eaw_dn_decompose_t decompose, const eaw_synthesize_t synthesize)
#define DT_IOP_DENOISE_PROFILE_V8_BANDS
static gboolean denoiseprofile_scrolled(GtkWidget *widget, GdkEventScroll *event, gpointer user_data)
static void denoiseprofile_tab_switch(GtkNotebook *notebook, GtkWidget *page, guint page_num, gpointer user_data)
dt_iop_denoiseprofile_mode_t
#define DT_IOP_DENOISE_PROFILE_P_FULCRUM
static __DT_CLONE_TARGETS__ void precondition_v2(const float *const in, float *const buf, const int wd, const int ht, const float a, const dt_aligned_pixel_t p, const float b, const dt_aligned_pixel_t wb)
void init_presets(dt_iop_module_so_t *self)
static void mode_callback(GtkWidget *w, dt_iop_module_t *self)
int process(struct dt_iop_module_t *self, const dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece, const void *const ivoid, void *const ovoid)
static __DT_CLONE_TARGETS__ void precondition_Y0U0V0(const float *const in, float *const buf, const int wd, const int ht, const float a, const dt_aligned_pixel_t p, const float b, const dt_colormatrix_t toY0U0V0)
static __DT_CLONE_TARGETS__ void sum_rec(const size_t npixels, const float *in, float *out)
static __DT_CLONE_TARGETS__ void variance_rec(const size_t npixels, const float *in, float *out, const dt_aligned_pixel_t mean)
void cleanup_pipe(struct dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
static gboolean denoiseprofile_leave_notify(GtkWidget *widget, GdkEventCrossing *event, gpointer user_data)
static gboolean denoiseprofile_motion_notify(GtkWidget *widget, GdkEventMotion *event, gpointer user_data)
static gboolean denoiseprofile_button_press(GtkWidget *widget, GdkEventButton *event, gpointer user_data)
void init_global(dt_iop_module_so_t *module)
static gboolean denoiseprofile_draw(GtkWidget *widget, cairo_t *crf, gpointer user_data)
int process_cl(struct dt_iop_module_t *self, const dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece, cl_mem dev_in, cl_mem dev_out)
static __DT_CLONE_TARGETS__ void precondition(const float *const in, float *const buf, const int wd, const int ht, const dt_aligned_pixel_t a, const dt_aligned_pixel_t b)
int legacy_params(dt_iop_module_t *self, const void *const old_params, const int old_version, void *new_params, const int new_version)
static unsigned infer_radius_from_profile(const float a)
#define dt_dev_add_history_item(dev, module, enable, redraw)
gboolean dt_dev_pixelpipe_has_preview_output(const dt_develop_t *dev, const dt_dev_pixelpipe_t *pipe, const dt_iop_roi_t *roi)
@ DT_DEV_PIXELPIPE_DISPLAY_MASK
static void dt_draw_curve_calc_values(dt_draw_curve_t *c, const float min, const float max, const int res, float *x, float *y)
static void dt_draw_grid(cairo_t *cr, const int num, const int left, const int top, const int right, const int bottom)
static float dt_draw_curve_calc_value(dt_draw_curve_t *c, const float x)
static void dt_draw_curve_destroy(dt_draw_curve_t *c)
static void dt_draw_curve_set_point(dt_draw_curve_t *c, const int num, const float x, const float y)
static int dt_draw_curve_add_point(dt_draw_curve_t *c, const float x, const float y)
static dt_draw_curve_t * dt_draw_curve_new(const float min, const float max, unsigned int type)
void eaw_dn_decompose(float *const restrict out, const float *const restrict in, float *const restrict detail, dt_aligned_pixel_t sum_squared, const int scale, const float inv_sigma2, const int32_t width, const int32_t height)
void eaw_synthesize(float *const out, const float *const in, const float *const restrict detail, const float *const restrict threshold, const float *const restrict boost, const int32_t width, const int32_t height)
gboolean dt_gui_get_scroll_unit_deltas(const GdkEventScroll *event, int *delta_x, int *delta_y)
GtkWidget * dt_ui_resizable_drawing_area(GtkWidget *area, char *config_str, int default_height, int min_height)
Make a self-drawing widget (typically a GtkDrawingArea graph or scope) vertically resizable.
GtkWidget * dt_ui_notebook_page(GtkNotebook *notebook, const char *text, const char *tooltip)
static cairo_surface_t * dt_cairo_image_surface_create(cairo_format_t format, int width, int height)
#define DT_GUI_BOX_SPACING
#define DT_PIXEL_APPLY_DPI(value)
static GtkWidget * dt_ui_label_new(const gchar *str)
void dt_gui_presets_add_generic(const char *name, dt_dev_operation_t op, const int32_t version, const void *params, const int32_t params_size, const int32_t enabled, const dt_develop_blend_colorspace_t blend_cst)
int dt_iop_alloc_image_buffers(struct dt_iop_module_t *const module, const struct dt_iop_roi_t *const roi_in, const struct dt_iop_roi_t *const roi_out,...)
void dt_iop_copy_image_roi(float *const __restrict__ out, const float *const __restrict__ in, const size_t ch, const dt_iop_roi_t *const __restrict__ roi_in, const dt_iop_roi_t *const __restrict__ roi_out, const int zero_pad)
void dt_iop_default_init(dt_iop_module_t *module)
const char ** dt_iop_set_description(dt_iop_module_t *module, const char *main_text, const char *purpose, const char *input, const char *process, const char *output)
@ IOP_FLAGS_SUPPORTS_BLENDING
#define IOP_GUI_ALLOC(module)
GtkWidget * dt_bauhaus_toggle_from_params(dt_iop_module_t *self, const char *param)
GtkWidget * dt_bauhaus_slider_from_params(dt_iop_module_t *self, const char *param)
GtkWidget * dt_bauhaus_combobox_from_params(dt_iop_module_t *self, const char *param)
float *const restrict const size_t k
float *const restrict const size_t const size_t ch
float DT_ALIGNED_ARRAY dt_colormatrix_t[4][4]
__DT_CLONE_TARGETS__ void nlmeans_denoise(const float *const inbuf, float *const outbuf, const dt_iop_roi_t *const roi_in, const dt_iop_roi_t *const roi_out, const dt_nlmeans_param_t *const params)
int nlmeans_denoiseprofile_cl(const dt_nlmeans_param_t *const params, const int devid, cl_mem dev_in, cl_mem dev_out, const dt_iop_roi_t *const roi_in)
float dt_aligned_pixel_t[4]
const dt_noiseprofile_t dt_noiseprofile_generic
void dt_noiseprofile_interpolate(const dt_noiseprofile_t *const p1, const dt_noiseprofile_t *const p2, dt_noiseprofile_t *out)
void dt_noiseprofile_free(gpointer data)
GList * dt_noiseprofile_get_matching(const dt_image_t *cimg)
int dt_opencl_local_buffer_opt(const int devid, const int kernel, dt_opencl_local_buffer_t *factors)
int dt_opencl_enqueue_kernel_2d(const int dev, const int kernel, const size_t *sizes)
void * dt_opencl_alloc_device_buffer(const int devid, const size_t size)
void * dt_opencl_alloc_device(const int devid, const int width, const int height, const int bpp)
int dt_opencl_create_kernel(const int prog, const char *name)
void * dt_opencl_copy_host_to_device_constant(const int devid, const size_t size, void *host)
int dt_opencl_enqueue_copy_image(const int devid, cl_mem src, cl_mem dst, size_t *orig_src, size_t *orig_dst, size_t *region)
int dt_opencl_read_buffer_from_device(const int devid, void *host, void *device, const size_t offset, const size_t size, const int blocking)
void dt_opencl_free_kernel(const int kernel)
int dt_opencl_set_kernel_arg(const int dev, const int kernel, const int num, const size_t size, const void *arg)
int dt_opencl_enqueue_kernel_2d_with_local(const int dev, const int kernel, const size_t *sizes, const size_t *local)
void dt_opencl_release_mem_object(cl_mem mem)
@ DT_DEV_PIXELPIPE_THUMBNAIL
Pixelpipe cache for storing intermediate results in the pixelpipe.
struct _GtkWidget GtkWidget
const float uint32_t state[4]
struct dt_gui_gtk_t * gui
struct dt_bauhaus_t * bauhaus
struct dt_develop_t * develop
PangoFontDescription * pango_font_desc
dt_iop_buffer_dsc_t dsc_in
struct dt_iop_module_t *void * data
gboolean cache_output_on_ram
dt_dev_pixelpipe_type_t type
dt_aligned_pixel_t coeffs
struct dt_iop_buffer_dsc_t::@30 temperature
dt_aligned_pixel_t processed_maximum
gboolean wb_adaptive_anscombe
dt_draw_curve_t * curve[DT_DENOISE_PROFILE_NONE]
float central_pixel_weight
dt_iop_denoiseprofile_wavelet_mode_t wavelet_color_mode
dt_iop_denoiseprofile_channel_t channel
float force[DT_DENOISE_PROFILE_NONE][7]
gboolean fix_anscombe_and_nlmeans_norm
dt_iop_denoiseprofile_mode_t mode
int kernel_denoiseprofile_horiz
int kernel_denoiseprofile_decompose
int kernel_denoiseprofile_backtransform_v2
int kernel_denoiseprofile_vert
int kernel_denoiseprofile_backtransform
int kernel_denoiseprofile_reduce_first
int kernel_denoiseprofile_backtransform_Y0U0V0
int kernel_denoiseprofile_reduce_second
int kernel_denoiseprofile_init
int kernel_denoiseprofile_precondition_Y0U0V0
int kernel_denoiseprofile_finish_v2
int kernel_denoiseprofile_finish
int kernel_denoiseprofile_synthesize
int kernel_denoiseprofile_accu
int kernel_denoiseprofile_precondition_v2
int kernel_denoiseprofile_dist
int kernel_denoiseprofile_precondition
GtkNotebook * channel_tabs_Y0U0V0
dt_iop_denoiseprofile_params_t drag_params
GtkWidget * wb_adaptive_anscombe
GtkWidget * wavelet_color_mode
dt_iop_denoiseprofile_channel_t channel
GtkWidget * fix_anscombe_and_nlmeans_norm
dt_noiseprofile_t interpolated
dt_draw_curve_t * transition_curve
GtkNotebook * channel_tabs
GtkWidget * central_pixel_weight
gboolean fix_anscombe_and_nlmeans_norm
float x[DT_DENOISE_PROFILE_NONE][7]
float central_pixel_weight
dt_iop_denoiseprofile_mode_t mode
float y[DT_DENOISE_PROFILE_NONE][7]
dt_iop_denoiseprofile_wavelet_mode_t wavelet_color_mode
gboolean wb_adaptive_anscombe
dt_iop_denoiseprofile_mode_t mode
gboolean wb_adaptive_anscombe
float x[DT_DENOISE_PROFILE_NONE][7]
float y[DT_DENOISE_PROFILE_NONE][7]
float central_pixel_weight
dt_iop_denoiseprofile_wavelet_mode_t wavelet_color_mode
gboolean fix_anscombe_and_nlmeans_norm
dt_iop_denoiseprofile_mode_t mode
dt_iop_denoiseprofile_mode_t mode
dt_iop_denoiseprofile_mode_t mode
dt_iop_denoiseprofile_mode_t mode
dt_iop_denoiseprofile_mode_t mode
float central_pixel_weight
gboolean wb_adaptive_anscombe
gboolean fix_anscombe_and_nlmeans_norm
gboolean fix_anscombe_and_nlmeans_norm
gboolean wb_adaptive_anscombe
float central_pixel_weight
dt_iop_denoiseprofile_mode_t mode
float central_pixel_weight
gboolean fix_anscombe_and_nlmeans_norm
dt_iop_denoiseprofile_mode_t mode
gboolean wb_adaptive_anscombe
GModule *dt_dev_operation_t op
dt_iop_global_data_t * data
dt_iop_params_t * default_params
struct dt_develop_t * dev
dt_iop_gui_data_t * gui_data
dt_iop_global_data_t * global_data
Region of interest passed through the pixelpipe.