71#include <json-glib/json-glib.h>
95#define USE_NEW_IMPL_CL 0
105#define DT_IOP_DENOISE_PROFILE_INSET DT_PIXEL_APPLY_DPI(5)
106#define DT_IOP_DENOISE_PROFILE_RES 64
107#define DT_IOP_DENOISE_PROFILE_V8_BANDS 5
108#define DT_IOP_DENOISE_PROFILE_BANDS 7
117#define DT_IOP_DENOISE_PROFILE_P_FULCRUM 0.05f
132#define DT_DENOISE_PROFILE_NONE_V9 4
398 const float*
const restrict buf,
const int width,
const int height,
const int scale)
403 snprintf(filename,
sizeof(filename), namespec, scale);
404 FILE *
f = g_fopen(filename,
"wb");
409 for(
size_t k=0;
k<
n;
k++)
410 fwrite(buf+4U*
k,
sizeof(
float), 3,
f);
416#define debug_dump_PFM(p,n,b,w,h,s)
420 void *new_params,
const int new_version)
422 if((old_version == 1 || old_version == 2 || old_version == 3) && new_version == 4)
436 memcpy(
n->a, o->
a,
sizeof(
float) * 3);
437 memcpy(
n->b, o->
b,
sizeof(
float) * 3);
461 if(!memcmp(interpolated.
a, o->
a,
sizeof(
float) * 3) && !memcmp(interpolated.
b, o->
b,
sizeof(
float) * 3))
468 else if(new_version == 5)
478 memcpy(&v4, old_params,
sizeof(v4));
493 v5->
x[c][b] = v4.
x[c][b];
494 v5->
y[c][b] = v4.
y[c][b];
500 else if(new_version == 6)
506 if(
legacy_params(self, old_params, old_version, &v5, 5))
return 1;
509 memcpy(&v5, old_params,
sizeof(v5));
516 for(
int k = 0;
k < 3;
k++)
525 v6->
x[c][b] = v5.
x[c][b];
526 v6->
y[c][b] = v5.
y[c][b];
532 else if(new_version == 7)
538 if(
legacy_params(self, old_params, old_version, &v6, 6))
return 1;
541 memcpy(&v6, old_params,
sizeof(v6));
547 for(
int k = 0;
k < 3;
k++)
556 v7->
x[c][b] = v6.
x[c][b];
557 v7->
y[c][b] = v6.
y[c][b];
566 else if(new_version == 8)
572 if(
legacy_params(self, old_params, old_version, &v7, 7))
return 1;
575 memcpy(&v7, old_params,
sizeof(v7));
581 for(
int k = 0;
k < 3;
k++)
590 v8->
x[c][b] = v7.
x[c][b];
591 v8->
y[c][b] = v7.
y[c][b];
604 else if(new_version == 9)
610 if(
legacy_params(self, old_params, old_version, &v8, 8))
return 1;
613 memcpy(&v8, old_params,
sizeof(v8));
619 for(
int k = 0;
k < 3;
k++)
649 else if(new_version == 10)
655 if(
legacy_params(self, old_params, old_version, &v9, 9))
return 1;
658 memcpy(&v9, old_params,
sizeof(v9));
669 for(
int k = 0;
k < 3;
k++)
678 v10->
x[c][b] = v9.
x[c][b];
679 v10->
y[c][b] = v9.
y[c][b];
698 else if(new_version == 11)
704 if(
legacy_params(self, old_params, old_version, v11, 10))
return 1;
707 memcpy(v11, old_params,
sizeof(*v11));
713 const float compensate_strength = 2.5f;
714 v11->
strength /= compensate_strength;
724 memset(&
p, 0,
sizeof(
p));
734 p.use_new_vst =
TRUE;
740 p.wb_adaptive_anscombe =
TRUE;
742 p.central_pixel_weight = 0.1f;
743 p.overshooting = 1.0f;
744 p.fix_anscombe_and_nlmeans_norm =
TRUE;
761 return _(
"de_noise (profiled)");
767 _(
"denoise using noise statistics profiled on sensors"),
769 _(
"linear, RGB, scene-referred"),
771 _(
"linear, RGB, scene-referred"));
802 const int P = ceilf(
d->radius * fminf(fminf(roi_in->
scale, 2.0f), 1.0f));
803 const int K = ceilf(
d->nbhood * fminf(fminf(roi_in->
scale, 2.0f), 1.0f));
804 const int K_scattered = ceilf(
d->scattering * (K * K * K + 7.0 * K * sqrt(K)) / 6.0) + K;
806 tiling->factor = 2.0f + 0.25f;
810 tiling->overlap =
P + K_scattered;
818 const float scale = fminf(roi_in->
scale, 1.0f);
821 = fminf(2 * (2u << (max_max_scale - 1)) + 1,
823 const float i0 = dt_log2f((supp0 - 1.0f) * .5f);
824 for(; max_scale < max_max_scale; max_scale++)
827 const float supp = 2 * (2u << max_scale) + 1;
829 const float supp_in = supp * (1.0f / scale);
830 const float i_in = dt_log2f((supp_in - 1) * .5f) - 1.0f;
832 const float t = 1.0f - (i_in + .5f) / i0;
836 const int max_filter_radius = (1u << max_scale);
839 tiling->factor_cl = 3.5f + max_scale;
843 tiling->overlap = max_filter_radius;
851static inline void precondition(
const float *
const in,
float *
const buf,
const int wd,
const int ht,
855 = { (b[0] / a[0]) * (b[0] / a[0]) + 3.f / 8.f,
856 (b[1] / a[1]) * (b[1] / a[1]) + 3.f / 8.f,
857 (b[2] / a[2]) * (b[2] / a[2]) + 3.f / 8.f,
859 const size_t npixels = (size_t)wd * ht;
861 for(
size_t j = 0; j < 4U * npixels; j += 4)
865 const float d = fmaxf(0.0f, in[j+c] / a[c] + sigma2_plus_3_8[c]);
866 buf[j+c] = 2.0f * sqrtf(
d);
876 = { (b[0] / a[0]) * (b[0] / a[0]) + 1.f / 8.f,
877 (b[1] / a[1]) * (b[1] / a[1]) + 1.f / 8.f,
878 (b[2] / a[2]) * (b[2] / a[2]) + 1.f / 8.f,
880 const size_t npixels = (size_t)wd * ht;
881 const float sqrt_3_2 = sqrtf(3.0f / 2.0f);
883 for(
size_t j = 0; j < 4U * npixels; j += 4)
887 const float x = buf[j+c], x2 =
x *
x;
889 buf[j+c] = (
x < 0.5f)
891 : a[c] * (1.f / 4.f * x2 + 1.f / 4.f * sqrt_3_2 /
x - 11.f / 8.f / x2
892 + 5.f / 8.f * sqrt_3_2 / (
x * x2) - sigma2_plus_1_8[c]);
924static inline void precondition_v2(
const float *
const in,
float *
const buf,
const int wd,
const int ht,
928 const size_t npixels = (size_t)wd * ht;
931 (-
p[2] + 2) * sqrtf(a), 1.0f };
933 for(
size_t j = 0; j < 4U * npixels; j += 4)
937 buf[j+c] = 2.0f * powf(
MAX(in[j+c] / wb[c] + b, 0.0f), expon[c]) / denom[c];
1002static inline void backtransform_v2(
float *
const buf,
const int wd,
const int ht,
const float a,
1006 const size_t npixels = (size_t)wd * ht;
1008 1.0f / (1.0f -
p[2] / 2.0f), 1.0f };
1009 const dt_aligned_pixel_t denom = { 4.0f / (sqrtf(a) * (2.0f -
p[0])), 4.0f / (sqrtf(a) * (2.0f -
p[1])),
1010 4.0f / (sqrtf(a) * (2.0f -
p[2])), 1.0f };
1012 for(
size_t j = 0; j < 4U * npixels; j += 4)
1016 const float x =
MAX(buf[j+c], 0.0f);
1017 const float delta =
x *
x + bias;
1018 const float z1 = (
x + sqrtf(
MAX(
delta, 0.0f))) / denom[c];
1019 buf[j+c] = wb[c] * (powf(z1, expon[c]) - b);
1031 2.0f / ((-
p[1] + 2) * sqrtf(a)),
1032 2.0f / ((-
p[2] + 2) * sqrtf(a)),
1035 for(
size_t j = 0; j < (size_t)4 * ht * wd; j += 4)
1040 tmp[c] = powf(
MAX(in[j+c] + b, 0.0f), expon[c]) * scale[c];
1042 for(
int c = 0; c < 3; c++)
1047 sum += toY0U0V0[c][
k] * tmp[
k];
1060 const dt_aligned_pixel_t bias_wb = { bias * wb[0], bias * wb[1], bias * wb[2], 0.0f };
1062 1.0f / (1.0f -
p[1] / 2.0f),
1063 1.0f / (1.0f -
p[2] / 2.0f),
1066 (sqrtf(a) * (2.0f -
p[1])) / 4.0f,
1067 (sqrtf(a) * (2.0f -
p[2])) / 4.0f,
1070 for(
size_t j = 0; j < (size_t)4 * ht * wd; j += 4)
1073 for(
int k = 0;
k < 3;
k++)
1077 rgb[
k] += toRGB[
k][c] * buf[j+c];
1082 const float x =
MAX(
rgb[c], 0.0f);
1083 const float delta =
x *
x + bias_wb[c];
1084 const float z1 = (
x + sqrtf(
MAX(
delta, 0.0f))) * scale[c];
1085 buf[j+c] = powf(z1, expon[c]) - b;
1105 wb[0] = wb[1] = wb[2] = wb[3] = wb_mean;
1106 if(
d->fix_anscombe_and_nlmeans_norm)
1108 if(wb_mean != 0.0f &&
d->wb_adaptive_anscombe)
1112 else if(wb_mean == 0.0f)
1135 const float biga = in[1][1] * in[2][2] - in[1][2] * in[2][1];
1136 const float bigb = -in[1][0] * in[2][2] + in[1][2] * in[2][0];
1137 const float bigc = in[1][0] * in[2][1] - in[1][1] * in[2][0];
1138 const float bigd = -in[0][1] * in[2][2] + in[0][2] * in[2][1];
1139 const float bige = in[0][0] * in[2][2] - in[0][2] * in[2][0];
1140 const float bigf = -in[0][0] * in[2][1] + in[0][1] * in[2][0];
1141 const float bigg = in[0][1] * in[1][2] - in[0][2] * in[1][1];
1142 const float bigh = -in[0][0] * in[1][2] + in[0][2] * in[1][0];
1143 const float bigi = in[0][0] * in[1][1] - in[0][1] * in[1][0];
1145 const float det = in[0][0] * biga + in[0][1] * bigb + in[0][2] * bigc;
1151 out[0][0] = 1.0f / det * biga;
1152 out[0][1] = 1.0f / det * bigd;
1153 out[0][2] = 1.0f / det * bigg;
1155 out[1][0] = 1.0f / det * bigb;
1156 out[1][1] = 1.0f / det * bige;
1157 out[1][2] = 1.0f / det * bigh;
1159 out[2][0] = 1.0f / det * bigc;
1160 out[2][1] = 1.0f / det * bigf;
1161 out[2][2] = 1.0f / det * bigi;
1178 float sum_invwb = 1.0f/wb[0] + 1.0f/wb[1] + 1.0f/wb[2];
1188 sum_invwb *= sqrtf(3);
1189 toY0U0V0[0][0] = sum_invwb / wb[0];
1190 toY0U0V0[0][1] = sum_invwb / wb[1];
1191 toY0U0V0[0][2] = sum_invwb / wb[2];
1192 toY0U0V0[0][3] = 0.0f;
1199 const float stddevU0 = sqrtf(0.5f * 0.5f * wb[0] * wb[0] + 0.5f * 0.5f * wb[2] * wb[2]);
1200 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]);
1201 toY0U0V0[1][0] /= stddevU0;
1202 toY0U0V0[1][1] /= stddevU0;
1203 toY0U0V0[1][2] /= stddevU0;
1204 toY0U0V0[1][3] = 0.0f;
1205 toY0U0V0[2][0] /= stddevV0;
1206 toY0U0V0[2][1] /= stddevV0;
1207 toY0U0V0[2][2] /= stddevV0;
1208 toY0U0V0[2][3] = 0.0f;
1209 const gboolean is_invertible = invert_matrix(toY0U0V0, toRGB);
1213 float stddevY0 = sqrtf(1.0f / 9.0f * (wb[0] * wb[0] + wb[1] * wb[1] + wb[2] * wb[2]));
1214 toY0U0V0[0][0] = 1.0f / (3.0f * stddevY0);
1215 toY0U0V0[0][1] = 1.0f / (3.0f * stddevY0);
1216 toY0U0V0[0][2] = 1.0f / (3.0f * stddevY0);
1217 toY0U0V0[0][3] = 0.0f;
1218 invert_matrix(toY0U0V0, toRGB);
1226 const float sigma = 1.0f;
1228 const float varf = sqrtf(2.0f + 2.0f * 4.0f * 4.0f + 6.0f * 6.0f) / 16.0f;
1229 const float sigma_band = powf(varf, scale) *
sigma;
1231 const float sb2 = sigma_band * sigma_band;
1232 const dt_aligned_pixel_t var_y = { sum_y2[0] / (npixels - 1.0f), sum_y2[1] / (npixels - 1.0f),
1233 sum_y2[2] / (npixels - 1.0f), 0.0f };
1235 sqrtf(
MAX(1e-6f, var_y[2] - sb2)), 1.0f };
1250 float band_force_exp_2
1252 band_force_exp_2 *= band_force_exp_2;
1253 band_force_exp_2 *= 4;
1256 adjt[
ch] *= band_force_exp_2;
1259 band_force_exp_2 *= band_force_exp_2;
1260 band_force_exp_2 *= 4;
1261 adjt[0] *= band_force_exp_2;
1263 band_force_exp_2 *= band_force_exp_2;
1264 band_force_exp_2 *= 4;
1265 adjt[1] *= band_force_exp_2;
1267 band_force_exp_2 *= band_force_exp_2;
1268 band_force_exp_2 *= 4;
1269 adjt[2] *= band_force_exp_2;
1274 band_force_exp_2 *= band_force_exp_2;
1275 band_force_exp_2 *= 4;
1276 adjt[0] *= band_force_exp_2;
1278 band_force_exp_2 *= band_force_exp_2;
1279 band_force_exp_2 *= 4;
1280 adjt[1] *= band_force_exp_2;
1281 adjt[2] *= band_force_exp_2;
1284 thrs[
c] = adjt[
c] * sb2 / std_x[
c];
1291 const dt_iop_roi_t *
const roi_out,
const eaw_dn_decompose_t decompose,
1292 const eaw_synthesize_t synthesize)
1298#define MAX_MAX_SCALE DT_IOP_DENOISE_PROFILE_BANDS
1301 const float in_scale = fminf(roi_in->
scale, 1.0f);
1305 const float i0 = dt_log2f((supp0 - 1.0f) * .5f);
1309 const float supp = 2 * (2u << max_scale) + 1;
1311 const float supp_in = supp * (1.0f / in_scale);
1312 const float i_in = dt_log2f((supp_in - 1) * .5f) - 1.0f;
1314 const float t = 1.0f - (i_in + .5f) / i0;
1318 const int max_mult = 1u << (max_scale - 1);
1321 const float *
const restrict in = (
const float*)ivoid;
1322 float *
const restrict
out = (
float*)
ovoid;
1328 memcpy(
out, in,
sizeof(
float) * 4 * npixels);
1333 float *restrict precond = NULL;
1334 float *restrict tmp = NULL;
1348 MAX(
d->shadows + 0.1 * logf(in_scale / wb[1]), 0.0f),
1349 MAX(
d->shadows + 0.1 * logf(in_scale / wb[2]), 0.0f),
1356 { 0.5f, 0.0f, -0.5f },
1357 { 0.25f, -0.5f, 0.25f } };
1359 { 0.0f, 0.0f, 0.0f },
1360 { 0.0f, 0.0f, 0.0f } };
1365 const float compensate_strength = (
d->wavelet_color_mode ==
MODE_RGB) ? 1.0f : 2.5f;
1367 for(
size_t k = 0;
k < 3;
k++)
1370 toY0U0V0[
k][c] /= (
d->strength * compensate_strength * in_scale);
1371 toRGB[
k][c] *= (
d->strength * compensate_strength * in_scale);
1383 else if(
d->wavelet_color_mode ==
MODE_RGB)
1394 float *restrict buf1 = precond;
1395 float *restrict buf2 = tmp;
1398 memset(
out, 0,
sizeof(
float) * 4 * npixels);
1400 for(
int scale = 0; scale < max_scale; scale++)
1402 const float sigma = 1.0f;
1403 const float varf = sqrtf(2.0f + 2.0f * 4.0f * 4.0f + 6.0f * 6.0f) / 16.0f;
1404 const float sigma_band = powf(varf, scale) *
sigma;
1406 decompose(buf2, buf1, buf, sum_y2, scale, 1.0f / (sigma_band * sigma_band),
width,
height);
1412 variance_stabilizing_xform(
thrs, scale, max_scale, npixels, sum_y2,
d);
1422 for (
size_t k = 0;
k < 4U * npixels;
k++)
1429 else if(
d->wavelet_color_mode ==
MODE_RGB)
1448#if defined(HAVE_OPENCL) && !USE_NEW_IMPL_CL
1451 return (a > 0) - (a < 0);
1463 float norm = .045f / ((2 *
P + 1) * (2 *
P + 1));
1464 if(!
d->fix_anscombe_and_nlmeans_norm)
1467 norm = .015f / (2 *
P + 1);
1479 float scattering =
d->scattering;
1485 const int maxk = (K * K * K + 7.0 * K * sqrt(K)) * scattering / 6.0 + K;
1487 scattering = (maxk - K) * 6.0 / (K * K * K + 7.0 * K * sqrt(K));
1492 const int maxk = (K * K * K + 7.0 * K * sqrt(K)) * scattering / 6.0 + K;
1493 K =
MAX(
MIN(4, K), K * scale);
1494 scattering = (maxk - K) * 6.0 / (K * K * K + 7.0 * K * sqrt(K));
1504 const void *
const ivoid,
const dt_iop_roi_t *
const roi_in,
1513 p[0] =
MAX(
d->shadows + 0.1 * logf(scale / wb[0]), 0.0f);
1514 p[1] =
MAX(
d->shadows + 0.1 * logf(scale / wb[1]), 0.0f);
1515 p[2] =
MAX(
d->shadows + 0.1 * logf(scale / wb[2]), 0.0f);
1521 wb[
i] *=
d->strength * scale;
1523 aa[
i] =
d->a[1] * wb[
i];
1524 bb[
i] =
d->b[1] * wb[
i];
1535 return compensate_p;
1552 p[0] =
MAX(
d->shadows + 0.1 * logf(scale / wb[0]), 0.0f);
1553 p[1] =
MAX(
d->shadows + 0.1 * logf(scale / wb[1]), 0.0f);
1554 p[2] =
MAX(
d->shadows + 0.1 * logf(scale / wb[2]), 0.0f);
1560 wb[
i] *=
d->strength * scale;
1562 aa[
i] =
d->a[1] * wb[
i];
1563 bb[
i] =
d->b[1] * wb[
i];
1572 aa[c] =
d->a[1] * compensate_p;
1576 return compensate_p;
1601 void (*denoiser)(
const float *
const inbuf,
float *
const outbuf,
1614 const float scale = fminf(fminf(roi_in->
scale, 2.0f), 1.0f);
1615 const int P = ceilf(
d->radius * scale);
1617 const float scattering = nlmeans_scattering(pipe, &K,
d, piece, scale);
1618 const float norm = nlmeans_norm(
P,
d);
1619 const float central_pixel_weight =
d->central_pixel_weight * scale;
1626 const float compensate_p = nlmeans_precondition(
d,piece,wb,ivoid,roi_in,scale,in,aa,bb,
p);
1633 .center_weight = central_pixel_weight,
1639 denoiser(in,
ovoid,roi_in,roi_out,¶ms);
1642 nlmeans_backtransform(
d,
ovoid,roi_in,scale,compensate_p,wb,aa,bb,
p);
1657static void sum_rec(
const size_t npixels,
const float *in,
float *
out)
1665 for(
size_t i = 0;
i < npixels;
i++)
1669 out[c] += in[
i * 4 + c];
1675 const size_t npixels_first_half = npixels >> 1;
1676 const size_t npixels_second_half = npixels - npixels_first_half;
1678 sum_rec(npixels_second_half, in + 4U * npixels_first_half,
out + 4U * npixels_first_half);
1681 out[c] +=
out[4U * npixels_first_half + c];
1695 for(
size_t i = 0;
i < npixels;
i++)
1699 const float diff = in[
i * 4 + c] - mean[c];
1700 out[c] += diff * diff;
1706 const size_t npixels_first_half = npixels >> 1;
1707 const size_t npixels_second_half = npixels - npixels_first_half;
1709 variance_rec(npixels_second_half, in + 4U * npixels_first_half,
out + 4U * npixels_first_half, mean);
1712 out[c] +=
out[4U * npixels_first_half + c];
1727 memcpy(
ovoid, ivoid,
sizeof(
float) * 4 * npixels);
1743 MAX(
d->shadows - 0.1 * logf(wb[1]), 0.0f),
1744 MAX(
d->shadows - 0.1 * logf(wb[2]), 0.0f),
1760 mean[
c] =
out[
c] / npixels;
1766 var[
c] =
out[
c] / (npixels - 1);
1768 g->variance_R = var[0];
1769 g->variance_G = var[1];
1770 g->variance_B = var[2];
1772 memcpy(
ovoid, ivoid,
sizeof(
float) * 4 * npixels);
1776#if defined(HAVE_OPENCL) && !USE_NEW_IMPL_CL
1779 unsigned int current = *
state;
1780 unsigned int next = (current >=
max - 1 ? 0 : current + 1);
1788#if defined(HAVE_OPENCL)
1801 const float scale = fminf(fminf(roi_in->
scale, 2.0f), 1.0f);
1802 const int P = ceilf(
d->radius * scale);
1804 const float scattering = nlmeans_scattering(pipe, &K,
d, piece, scale);
1805 const float norm = nlmeans_norm(
P,
d);
1806 const float central_pixel_weight =
d->central_pixel_weight * scale;
1815 const int devid = pipe->
devid;
1824 const float sigma2[4] = { (bb[0] / aa[0]) * (bb[0] / aa[0]), (bb[1] / aa[1]) * (bb[1] / aa[1]),
1825 (bb[2] / aa[2]) * (bb[2] / aa[2]), 0.0f };
1854 if (err == CL_SUCCESS)
1859 .scattering = scattering,
1863 .center_weight = central_pixel_weight,
1869 .pipetype = pipe->
type,
1878 if (err == CL_SUCCESS)
1893 const float bias =
d->bias - 0.5 * logf(scale);
1909 if (err == CL_SUCCESS)
1920 const float scale = fminf(fminf(roi_in->
scale, 2.0f), 1.0f);
1921 const int P = ceilf(
d->radius * scale);
1923 const float scattering = nlmeans_scattering(pipe, &K,
d, piece, scale);
1924 const float norm = nlmeans_norm(
P,
d);
1925 const float central_pixel_weight =
d->central_pixel_weight * scale;
1933 const dt_aligned_pixel_t sigma2 = { (bb[0] / aa[0]) * (bb[0] / aa[0]), (bb[1] / aa[1]) * (bb[1] / aa[1]),
1934 (bb[2] / aa[2]) * (bb[2] / aa[2]), 0.0f };
1936 const int devid = pipe->
devid;
1944 unsigned int state = 0;
1948 if(buckets[
k] == NULL)
goto error;
1954 .cellsize =
sizeof(float), .overhead = 0,
1955 .sizex = 1u << 16, .sizey = 1 };
1958 hblocksize = hlocopt.
sizex;
1965 .cellsize =
sizeof(float), .overhead = 0,
1966 .sizex = 1, .sizey = 1u << 16 };
1969 vblocksize = vlocopt.
sizey;
1987 if(err != CL_SUCCESS)
goto error;
2000 if(err != CL_SUCCESS)
goto error;
2007 if(err != CL_SUCCESS)
goto error;
2012 for(
int kj_index = -K; kj_index <= 0; kj_index++)
2014 for(
int ki_index = -K; ki_index <= K; ki_index++)
2020 const int abs_kj = abs(kj_index);
2021 const int abs_ki = abs(ki_index);
2022 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);
2023 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);
2024 int q[2] = {
i, j };
2033 if(err != CL_SUCCESS)
goto error;
2038 local[0] = hblocksize;
2051 if(err != CL_SUCCESS)
goto error;
2054 sizesl[1] = bheight;
2057 local[1] = vblocksize;
2070 (
void *)¢ral_pixel_weight);
2073 if(err != CL_SUCCESS)
goto error;
2083 if(err != CL_SUCCESS)
goto error;
2097 if(err != CL_SUCCESS)
goto error;
2101 const float bias =
d->bias - 0.5 * logf(scale);
2113 if(err != CL_SUCCESS)
goto error;
2146 const float scale = fminf(roi_in->
scale, 1.0f);
2149 =
MIN(2 * (2u << (max_max_scale - 1)) + 1,
2151 const float i0 = dt_log2f((supp0 - 1.0f) * .5f);
2152 for(; max_scale < max_max_scale; max_scale++)
2155 const float supp = 2 * (2u << max_scale) + 1;
2157 const float supp_in = supp * (1.0f / scale);
2158 const float i_in = dt_log2f((supp_in - 1) * .5f) - 1.0f;
2160 const float t = 1.0f - (i_in + .5f) / i0;
2164 const int devid = pipe->
devid;
2170 cl_mem dev_tmp = NULL;
2171 cl_mem dev_buf1 = NULL;
2172 cl_mem dev_buf2 = NULL;
2173 cl_mem dev_m = NULL;
2174 cl_mem dev_r = NULL;
2175 cl_mem dev_filter = NULL;
2176 cl_mem *dev_detail = calloc(max_max_scale,
sizeof(cl_mem));
2177 float *sumsum = NULL;
2184 size_t origin[] = { 0, 0, 0 };
2187 if(err != CL_SUCCESS)
goto error;
2194 .cellsize = 4 *
sizeof(float), .overhead = 0,
2195 .sizex = 1u << 4, .sizey = 1u << 4 };
2203 const int bufsize = (bwidth / flocopt.
sizex) * (bheight / flocopt.
sizey);
2207 .cellsize = 4 *
sizeof(float), .overhead = 0,
2208 .sizex = 1u << 16, .sizey = 1 };
2228 float m[] = { 0.0625f, 0.25f, 0.375f, 0.25f, 0.0625f };
2230 for(
int j = 0; j < 5; j++)
2231 for(
int i = 0;
i < 5;
i++) mm[j][
i] =
m[
i] *
m[j];
2236 for(
int k = 0;
k < max_scale;
k++)
2239 if(dev_detail[
k] == NULL)
goto error;
2249 MAX(
d->shadows + 0.1 * logf(scale / wb[1]), 0.0f),
2250 MAX(
d->shadows + 0.1 * logf(scale / wb[2]), 0.0f), 1.0f};
2254 { 0.5f, 0.0f, -0.5f },
2255 { 0.25f, -0.5f, 0.25f } };
2257 { 0.0f, 0.0f, 0.0f },
2258 { 0.0f, 0.0f, 0.0f } };
2263 const float compensate_strength = (
d->wavelet_color_mode ==
MODE_RGB) ? 1.0f : 2.5f;
2268 for(
size_t k = 0;
k < 3;
k++)
2269 for(
size_t c = 0; c < 3; c++)
2272 toRGB[3*
k+c] = toRGB_tmp[
k][c] *
d->strength * compensate_strength * scale;
2273 toY0U0V0[3*
k+c] = toY0U0V0_tmp[
k][c] / (
d->strength * compensate_strength * scale);
2281 const dt_aligned_pixel_t sigma2 = { (bb[0] / aa[0]) * (bb[0] / aa[0]), (bb[1] / aa[1]) * (bb[1] / aa[1]),
2282 (bb[2] / aa[2]) * (bb[2] / aa[2]), 0.0f };
2288 aa[c] =
d->a[1] * compensate_p;
2304 if(err != CL_SUCCESS)
goto error;
2306 else if(
d->wavelet_color_mode ==
MODE_RGB)
2317 if(err != CL_SUCCESS)
goto error;
2321 cl_mem dev_Y0U0V0 = NULL;
2335 if(err != CL_SUCCESS)
goto error;
2348 for(
int s = 0; s < max_scale; s++)
2350 const float sigma = 1.0f;
2351 const float varf = sqrtf(2.0f + 2.0f * 4.0f * 4.0f + 6.0f * 6.0f) / 16.0f;
2352 const float sigma_band = powf(varf, s) *
sigma;
2353 const float inv_sigma2 = 1.0f / (sigma_band * sigma_band);
2358 (
void *)&dev_detail[s]);
2364 (
void *)&inv_sigma2);
2366 (
void *)&dev_filter);
2368 if(err != CL_SUCCESS)
goto error;
2371 cl_mem dev_buf3 = dev_buf2;
2372 dev_buf2 = dev_buf1;
2373 dev_buf1 = dev_buf3;
2377 for(
int s = max_scale - 1; s >= 0; s--)
2380 const float sigma = 1.0f;
2382 const float varf = sqrtf(2.0f + 2.0f * 4.0f * 4.0f + 6.0f * 6.0f) / 16.0f;
2383 const float sigma_band = powf(varf, s) *
sigma;
2392 lsizes[1] = bheight;
2394 llocal[0] = flocopt.
sizex;
2395 llocal[1] = flocopt.
sizey;
2403 sizeof(
float) * 4 * flocopt.
sizex * flocopt.
sizey, NULL);
2406 if(err != CL_SUCCESS)
goto error;
2409 lsizes[0] = (size_t)reducesize * slocopt.
sizex;
2412 llocal[0] = slocopt.
sizex;
2422 if(err != CL_SUCCESS)
goto error;
2425 sizeof(
float) * 4 * reducesize, CL_TRUE);
2426 if(err != CL_SUCCESS)
2429 for(
int k = 0;
k < reducesize;
k++)
2433 sum_y2[c] += sumsum[4 *
k + c];
2437 const float sb2 = sigma_band * sigma_band;
2438 const dt_aligned_pixel_t var_y = { sum_y2[0] / (npixels - 1.0f), sum_y2[1] / (npixels - 1.0f),
2439 sum_y2[2] / (npixels - 1.0f), 0.0f };
2441 sqrtf(
MAX(1e-6f, var_y[2] - sb2)), 1.0f };
2457 band_force_exp_2 *= band_force_exp_2;
2458 band_force_exp_2 *= 4;
2461 adjt[
ch] *= band_force_exp_2;
2464 band_force_exp_2 *= band_force_exp_2;
2465 band_force_exp_2 *= 4;
2466 adjt[0] *= band_force_exp_2;
2468 band_force_exp_2 *= band_force_exp_2;
2469 band_force_exp_2 *= 4;
2470 adjt[1] *= band_force_exp_2;
2472 band_force_exp_2 *= band_force_exp_2;
2473 band_force_exp_2 *= 4;
2474 adjt[2] *= band_force_exp_2;
2479 band_force_exp_2 *= band_force_exp_2;
2480 band_force_exp_2 *= 4;
2481 adjt[0] *= band_force_exp_2;
2483 band_force_exp_2 *= band_force_exp_2;
2484 band_force_exp_2 *= 4;
2485 adjt[1] *= band_force_exp_2;
2486 adjt[2] *= band_force_exp_2;
2490 adjt[2] * sb2 / std_x[2], 0.0f };
2498 (
void *)&dev_detail[s]);
2515 if(err != CL_SUCCESS)
goto error;
2518 cl_mem dev_buf3 = dev_buf2;
2519 dev_buf2 = dev_buf1;
2520 dev_buf1 = dev_buf3;
2525 if(dev_buf1 != dev_tmp)
2527 size_t origin[] = { 0, 0, 0 };
2530 if(err != CL_SUCCESS)
goto error;
2542 if(err != CL_SUCCESS)
goto error;
2544 else if(
d->wavelet_color_mode ==
MODE_RGB)
2546 const float bias =
d->bias - 0.5 * logf(scale);
2557 if(err != CL_SUCCESS)
goto error;
2561 cl_mem dev_RGB = NULL;
2565 const float bias =
d->bias - 0.5 * logf(scale);
2578 if(err != CL_SUCCESS)
goto error;
2591 for(
int k = 0;
k < max_scale;
k++)
2602 for(
int k = 0;
k < max_scale;
k++)
2640 err = process_nlmeans(pipe, piece, ivoid,
ovoid, roi_in, roi_out);
2644 err = process_variance(self, pipe, piece, ivoid,
ovoid, roi_in, roi_out);
2650 return MIN((
unsigned)(1.0f + a * 15000.0f + a * a * 300000.0f), 8);
2655 return MIN(3000.0f * a, 1.0f);
2660 return MIN(
MAX(0.1f - 0.1 * logf(a), 0.7f), 1.8f);
2665 return -
MAX(5 + 0.5 * logf(a), 0.0);
2693 const int iso =
module->dev->image_storage.exif_iso;
2695 for(GList *iter = profiles; iter; iter = g_list_next(iter))
2698 if(current->
iso == iso)
2700 interpolated = *current;
2701 interpolated.
a[0] = -1.0f;
2704 if(last && last->
iso < iso && current->
iso > iso)
2706 interpolated.
iso = iso;
2708 interpolated.
a[0] = -1.0f;
2714 return interpolated;
2725 const float a = interpolated.
a[1];
2733 for(
int k = 0;
k < 3;
k++)
2735 d->a[
k] = interpolated.
a[
k];
2736 d->b[
k] = interpolated.
b[
k];
2742 const int program = 11;
2793 for(GList *iter = profiles; iter; iter = g_list_next(iter))
2796 if(current->
iso == iso)
2798 interpolated = *current;
2801 if(last && last->
iso < iso && current->
iso > iso)
2803 interpolated.
iso = iso;
2811 return interpolated;
2821 d->nbhood =
p->nbhood;
2822 d->central_pixel_weight =
p->central_pixel_weight;
2823 d->strength =
p->strength;
2824 d->overshooting =
p->overshooting;
2825 for(
int i = 0;
i < 3;
i++)
2831 d->wavelet_color_mode =
p->wavelet_color_mode;
2840 for(
int k = 0;
k < 3;
k++)
2842 d->a[
k] = interpolated.
a[
k];
2843 d->b[
k] = interpolated.
b[
k];
2849 const float gain =
p->overshooting;
2857 d->radius =
p->radius;
2858 d->scattering =
p->scattering;
2859 d->shadows =
p->shadows;
2873 d->wb_adaptive_anscombe =
p->wb_adaptive_anscombe;
2874 d->fix_anscombe_and_nlmeans_norm =
p->fix_anscombe_and_nlmeans_norm;
2875 d->use_new_vst =
p->use_new_vst;
2884 piece->
data = (
void *)
d;
2917 for(
int k = 0;
k < 3;
k++)
2919 p->
a[
k] = profile->
a[
k];
2920 p->b[
k] = profile->
b[
k];
2934 gtk_widget_hide(
g->box_wavelets);
2935 gtk_widget_hide(
g->box_variance);
2936 gtk_widget_show_all(
g->box_nlm);
2940 gtk_widget_hide(
g->box_wavelets);
2941 gtk_widget_hide(
g->box_variance);
2942 gtk_widget_show_all(
g->box_nlm);
2943 gtk_widget_set_visible(
g->radius,
FALSE);
2944 gtk_widget_set_visible(
g->nbhood,
FALSE);
2945 gtk_widget_set_visible(
g->scattering,
FALSE);
2949 gtk_widget_hide(
g->box_nlm);
2950 gtk_widget_hide(
g->box_variance);
2951 gtk_widget_show_all(
g->box_wavelets);
2952 gtk_widget_set_visible(GTK_WIDGET(
g->wavelet_color_mode),
p->use_new_vst);
2953 gtk_widget_set_visible(GTK_WIDGET(
g->channel_tabs),
p->use_new_vst && (
p->wavelet_color_mode ==
MODE_RGB));
2954 gtk_widget_set_visible(GTK_WIDGET(
g->channel_tabs_Y0U0V0),
p->use_new_vst && (
p->wavelet_color_mode ==
MODE_Y0U0V0));
2958 gtk_widget_hide(
g->box_nlm);
2959 gtk_widget_hide(
g->box_variance);
2960 gtk_widget_show_all(
g->box_wavelets);
2961 gtk_widget_set_visible(GTK_WIDGET(
g->wavelet_color_mode),
p->use_new_vst);
2962 gtk_widget_set_visible(GTK_WIDGET(
g->channel_tabs),
p->use_new_vst && (
p->wavelet_color_mode ==
MODE_RGB));
2963 gtk_widget_set_visible(GTK_WIDGET(
g->channel_tabs_Y0U0V0),
p->use_new_vst && (
p->wavelet_color_mode ==
MODE_Y0U0V0));
2967 gtk_widget_hide(
g->box_wavelets);
2968 gtk_widget_hide(
g->box_nlm);
2969 gtk_widget_show_all(
g->box_variance);
2973 gtk_widget_set_visible(
g->shadows,
p->use_new_vst && !auto_mode);
2974 gtk_widget_set_visible(
g->bias,
p->use_new_vst && !auto_mode);
2975 gtk_widget_set_visible(
g->overshooting, auto_mode);
2984 if(w ==
g->wavelet_color_mode)
2986 gtk_widget_set_visible(GTK_WIDGET(
g->channel_tabs), (
p->wavelet_color_mode ==
MODE_RGB));
2987 gtk_widget_set_visible(GTK_WIDGET(
g->channel_tabs_Y0U0V0), (
p->wavelet_color_mode ==
MODE_Y0U0V0));
2993 else if(w ==
g->overshooting)
2995 const float gain =
p->overshooting;
3000 a = interpolated.
a[1];
3006 gtk_widget_set_visible(
g->radius,
TRUE);
3007 gtk_widget_set_visible(
g->scattering,
TRUE);
3010 gtk_widget_set_visible(
g->radius,
FALSE);
3011 gtk_widget_set_visible(
g->scattering,
FALSE);
3017 gtk_widget_show_all(
g->box_nlm);
3020 gtk_widget_hide(
g->box_nlm);
3022 gtk_widget_set_visible(
g->shadows,
TRUE);
3023 gtk_widget_set_visible(
g->bias,
TRUE);
3026 gtk_widget_set_visible(
g->shadows,
FALSE);
3027 gtk_widget_set_visible(
g->bias,
FALSE);
3029 else if(w ==
g->use_new_vst)
3032 gtk_widget_set_visible(
g->shadows,
p->use_new_vst && !auto_mode);
3033 gtk_widget_set_visible(
g->bias,
p->use_new_vst && !auto_mode);
3034 gtk_widget_set_visible(
g->wavelet_color_mode,
p->use_new_vst);
3057 g_strlcpy(
name, _(
g->interpolated.name),
sizeof(
name));
3061 for(GList *iter =
g->profiles; iter; iter = g_list_next(iter))
3064 if(current->
iso == iso)
3066 g->interpolated = *current;
3067 g->interpolated.
a[0] = -1.0f;
3068 snprintf(
name,
sizeof(
name), _(
"found match for ISO %d"), iso);
3071 if(last && last->
iso < iso && current->
iso > iso)
3073 g->interpolated.iso = iso;
3075 g->interpolated.a[0] = -1.0f;
3076 snprintf(
name,
sizeof(
name), _(
"interpolated from ISO %d and %d"), last->
iso, current->
iso);
3082 for(GList *iter =
g->profiles; iter; iter = g_list_next(iter))
3096 unsigned combobox_index = 0;
3101 gtk_widget_hide(
g->box_wavelets);
3102 gtk_widget_hide(
g->box_variance);
3103 gtk_widget_show_all(
g->box_nlm);
3107 gtk_widget_hide(
g->box_wavelets);
3108 gtk_widget_hide(
g->box_variance);
3109 gtk_widget_show_all(
g->box_nlm);
3110 gtk_widget_set_visible(
g->radius,
FALSE);
3111 gtk_widget_set_visible(
g->nbhood,
FALSE);
3112 gtk_widget_set_visible(
g->scattering,
FALSE);
3116 gtk_widget_hide(
g->box_nlm);
3117 gtk_widget_hide(
g->box_variance);
3118 gtk_widget_show_all(
g->box_wavelets);
3122 gtk_widget_hide(
g->box_nlm);
3123 gtk_widget_hide(
g->box_variance);
3124 gtk_widget_show_all(
g->box_wavelets);
3128 gtk_widget_hide(
g->box_wavelets);
3129 gtk_widget_hide(
g->box_nlm);
3130 gtk_widget_show_all(
g->box_variance);
3141 a = interpolated.
a[1];
3145 const float gain =
p->overshooting;
3159 for(GList *iter =
g->profiles; iter; iter = g_list_next(iter),
i++)
3162 if(!memcmp(profile->
a,
p->a,
sizeof(
float) * 3)
3163 && !memcmp(profile->
b,
p->b,
sizeof(
float) * 3))
3170 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(
g->wb_adaptive_anscombe),
p->wb_adaptive_anscombe);
3171 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(
g->fix_anscombe_and_nlmeans_norm),
p->fix_anscombe_and_nlmeans_norm);
3172 gtk_widget_set_visible(
g->fix_anscombe_and_nlmeans_norm, !
p->fix_anscombe_and_nlmeans_norm);
3173 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(
g->use_new_vst),
p->use_new_vst);
3174 gtk_widget_set_visible(
g->use_new_vst, !
p->use_new_vst);
3177 gtk_widget_set_visible(
g->overshooting, auto_mode);
3178 gtk_widget_set_visible(
g->wavelet_color_mode,
p->use_new_vst && wavelet_mode);
3179 gtk_widget_set_visible(
g->shadows,
p->use_new_vst && !auto_mode);
3180 gtk_widget_set_visible(
g->bias,
p->use_new_vst && !auto_mode);
3181 gtk_widget_set_visible(GTK_WIDGET(
g->channel_tabs), (
p->wavelet_color_mode ==
MODE_RGB));
3182 gtk_widget_set_visible(GTK_WIDGET(
g->channel_tabs_Y0U0V0), (
p->wavelet_color_mode ==
MODE_Y0U0V0));
3191 gtk_notebook_set_current_page(GTK_NOTEBOOK(
g->channel_tabs),
g->channel);
3207 gtk_notebook_set_current_page(GTK_NOTEBOOK(
g->channel_tabs),
g->channel);
3209 gtk_widget_set_visible(
g->fix_anscombe_and_nlmeans_norm, !
p->fix_anscombe_and_nlmeans_norm);
3210 gtk_widget_set_visible(
g->use_new_vst, !
p->use_new_vst);
3214 const double mouse_y,
const float rad)
3218 const float f = expf(-(mouse_x -
p->x[
ch][
k]) * (mouse_x -
p->x[
ch][
k]) / (rad * rad));
3219 p->y[
ch][
k] = (1 -
f) *
p->y[
ch][
k] +
f * mouse_y;
3230 if(!isnan(c->variance_R))
3232 gchar *str = g_strdup_printf(
"%.2f", c->variance_R);
3234 gtk_label_set_text(c->label_var_R, str);
3238 if(!isnan(c->variance_G))
3240 gchar *str = g_strdup_printf(
"%.2f", c->variance_G);
3242 gtk_label_set_text(c->label_var_G, str);
3246 if(!isnan(c->variance_B))
3248 gchar *str = g_strdup_printf(
"%.2f", c->variance_B);
3250 gtk_label_set_text(c->label_var_B, str);
3263 int ch = (int)c->channel;
3271 GtkAllocation allocation;
3272 gtk_widget_get_allocation(widget, &allocation);
3273 int width = allocation.width,
height = allocation.height;
3275 cairo_t *cr = cairo_create(cst);
3276 cairo_set_source_rgb(cr, .2, .2, .2);
3280 cairo_translate(cr, inset, inset);
3285 cairo_set_source_rgb(cr, .1, .1, .1);
3289 cairo_set_source_rgb(cr, .3, .3, .3);
3295 cairo_set_source_rgb(cr, .1, .1, .1);
3298 if(c->mouse_y > 0 || c->dragging)
3324 cairo_translate(cr, 0,
height);
3326 cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
3340 cairo_set_source_rgba(cr, .7, .7, .7, alpha);
3343 cairo_set_source_rgba(cr, .7, .1, .1, alpha);
3346 cairo_set_source_rgba(cr, .1, .7, .1, alpha);
3349 cairo_set_source_rgba(cr, .1, .1, .7, alpha);
3352 cairo_set_source_rgba(cr, 7, .7, .7, 0.0f);
3361 cairo_set_source_rgba(cr, .7, .7, .7, alpha);
3364 cairo_set_source_rgba(cr, .8, .4, .0, alpha);
3367 cairo_set_source_rgba(cr, .7, .7, .7, 0.0f);
3387 cairo_set_source_rgb(cr, 0.7, 0.7, 0.7);
3398 if(c->mouse_y > 0 || c->dragging)
3401 cairo_set_source_rgba(cr, .7, .7, .7, .6);
3402 cairo_move_to(cr, 0, -
height * c->draw_min_ys[0]);
3407 cairo_close_path(cr);
3410 cairo_set_source_rgba(cr, .9, .9, .9, .5);
3413 const float f =
k - pos;
3415 float ht = -
height * (
f * c->draw_ys[
k] + (1 -
f) * c->draw_ys[
k + 1]);
3416 cairo_arc(cr, c->mouse_x *
width, ht, c->mouse_radius *
width, 0, 2. *
M_PI);
3422 cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
3425 PangoLayout *layout;
3427 PangoFontDescription *desc = pango_font_description_copy_static(
dt_bauhaus_get_global()->pango_font_desc);
3428 pango_font_description_set_weight(desc, PANGO_WEIGHT_BOLD);
3429 pango_font_description_set_absolute_size(desc, (.08 *
height) * PANGO_SCALE);
3430 layout = pango_cairo_create_layout(cr);
3431 pango_layout_set_font_description(layout, desc);
3432 cairo_set_source_rgb(cr, .1, .1, .1);
3434 pango_layout_set_text(layout, _(
"coarse"), -1);
3435 pango_layout_get_pixel_extents(layout, &ink, NULL);
3436 cairo_move_to(cr, .02 *
width - ink.y, .5 * (
height + ink.width));
3438 cairo_rotate(cr, -
M_PI * .5f);
3439 pango_cairo_show_layout(cr, layout);
3442 pango_layout_set_text(layout, _(
"fine"), -1);
3443 pango_layout_get_pixel_extents(layout, &ink, NULL);
3444 cairo_move_to(cr, .98 *
width - ink.height, .5 * (
height + ink.width));
3446 cairo_rotate(cr, -
M_PI * .5f);
3447 pango_cairo_show_layout(cr, layout);
3451 pango_layout_set_text(layout, _(
"smooth"), -1);
3452 pango_layout_get_pixel_extents(layout, &ink, NULL);
3453 cairo_move_to(cr, .5 * (
width - ink.width), .08 *
height - ink.height);
3454 pango_cairo_show_layout(cr, layout);
3456 pango_layout_set_text(layout, _(
"noisy"), -1);
3457 pango_layout_get_pixel_extents(layout, &ink, NULL);
3458 cairo_move_to(cr, .5 * (
width - ink.width), .97 *
height - ink.height);
3459 pango_cairo_show_layout(cr, layout);
3461 pango_font_description_free(desc);
3462 g_object_unref(layout);
3464 cairo_set_source_surface(crf, cst, 0, 0);
3466 cairo_surface_destroy(cst);
3476 GtkAllocation allocation;
3477 gtk_widget_get_allocation(widget, &allocation);
3478 int height = allocation.height - 2 * inset,
width = allocation.width - 2 * inset;
3479 if(!c->dragging) c->mouse_x = CLAMP(event->x - inset, 0,
width) / (float)
width;
3480 c->mouse_y = 1.0 - CLAMP(event->y - inset, 0,
height) / (float)
height;
3483 *
p = c->drag_params;
3494 gtk_widget_queue_draw(widget);
3502 const int ch = c->channel;
3503 if(event->button == 1 && event->type == GDK_2BUTTON_PRESS)
3515 gtk_widget_queue_draw(self->
gui->
widget);
3517 else if(event->button == 1)
3521 GtkAllocation allocation;
3522 gtk_widget_get_allocation(widget, &allocation);
3523 int height = allocation.height - 2 * inset,
width = allocation.width - 2 * inset;
3526 c->mouse_pick -= 1.0 - CLAMP(event->y - inset, 0,
height) / (float)
height;
3535 if(event->button == 1)
3549 if(!c->dragging) c->mouse_y = -1.0;
3550 gtk_widget_queue_draw(widget);
3563 gtk_widget_queue_draw(widget);
3579 gtk_widget_queue_draw(self->
gui->
widget);
3608 g->channel_tabs = GTK_NOTEBOOK(gtk_notebook_new());
3614 gtk_box_pack_start(GTK_BOX(
g->box_wavelets), GTK_WIDGET(
g->channel_tabs),
FALSE,
FALSE, 0);
3616 g->channel_tabs_Y0U0V0 = GTK_NOTEBOOK(gtk_notebook_new());
3620 gtk_box_pack_start(GTK_BOX(
g->box_wavelets), GTK_WIDGET(
g->channel_tabs_Y0U0V0),
FALSE,
FALSE, 0);
3622 const int ch = (int)
g->channel;
3630 g->mouse_x =
g->mouse_y =
g->mouse_pick = -1.0;
3635 g->area = GTK_DRAWING_AREA(gtk_drawing_area_new());
3636 gtk_widget_set_hexpand(GTK_WIDGET(
g->area),
TRUE);
3638 gtk_widget_add_events(GTK_WIDGET(
g->area), GDK_POINTER_MOTION_MASK
3639 | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK
3647 gtk_box_pack_start(GTK_BOX(
g->box_wavelets),
3649 "plugins/darkroom/denoiseprofile/graphheight", 280, 100),
3655 "uniform image if you want to\n"
3656 "estimate the noise variance.")));
3657 gtk_box_pack_start(GTK_BOX(
g->box_variance), GTK_WIDGET(
g->label_var),
TRUE,
TRUE, 0);
3659 GtkBox *hboxR = GTK_BOX(gtk_box_new(GTK_ORIENTATION_HORIZONTAL,
DT_GUI_BOX_SPACING));
3661 gtk_box_pack_start(GTK_BOX(hboxR), GTK_WIDGET(labelR),
FALSE,
FALSE, 0);
3663 gtk_widget_set_tooltip_text(GTK_WIDGET(
g->label_var_R), _(
"variance computed on the red channel"));
3664 gtk_box_pack_start(GTK_BOX(hboxR), GTK_WIDGET(
g->label_var_R),
FALSE,
FALSE, 0);
3665 gtk_box_pack_start(GTK_BOX(
g->box_variance), GTK_WIDGET(hboxR),
TRUE,
TRUE, 0);
3667 GtkBox *hboxG = GTK_BOX(gtk_box_new(GTK_ORIENTATION_HORIZONTAL,
DT_GUI_BOX_SPACING));
3669 gtk_box_pack_start(GTK_BOX(hboxG), GTK_WIDGET(labelG),
FALSE,
FALSE, 0);
3671 gtk_widget_set_tooltip_text(GTK_WIDGET(
g->label_var_G), _(
"variance computed on the green channel"));
3672 gtk_box_pack_start(GTK_BOX(hboxG), GTK_WIDGET(
g->label_var_G),
FALSE,
FALSE, 0);
3673 gtk_box_pack_start(GTK_BOX(
g->box_variance), GTK_WIDGET(hboxG),
TRUE,
TRUE, 0);
3675 GtkBox *hboxB = GTK_BOX(gtk_box_new(GTK_ORIENTATION_HORIZONTAL,
DT_GUI_BOX_SPACING));
3677 gtk_box_pack_start(GTK_BOX(hboxB), GTK_WIDGET(labelB),
FALSE,
FALSE, 0);
3679 gtk_widget_set_tooltip_text(GTK_WIDGET(
g->label_var_B), _(
"variance computed on the blue channel"));
3680 gtk_box_pack_start(GTK_BOX(hboxB), GTK_WIDGET(
g->label_var_B),
FALSE,
FALSE, 0);
3681 gtk_box_pack_start(GTK_BOX(
g->box_variance), GTK_WIDGET(hboxB),
TRUE,
TRUE, 0);
3690 g_signal_connect(G_OBJECT(
g->profile),
"value-changed", G_CALLBACK(
profile_callback), self);
3701 const gboolean compute_variance =
dt_conf_get_bool(
"plugins/darkroom/denoiseprofile/show_compute_variance_mode");
3703 g_signal_connect(G_OBJECT(
g->mode),
"value-changed", G_CALLBACK(
mode_callback), self);
3730 gtk_widget_set_tooltip_text(
g->wb_adaptive_anscombe, _(
"adapt denoising according to the\n"
3731 "white balance coefficients.\n"
3732 "should be enabled on a first instance\n"
3733 "for better denoising.\n"
3734 "should be disabled if an earlier instance\n"
3735 "has been used with a color blending mode."));
3736 gtk_widget_set_tooltip_text(
g->fix_anscombe_and_nlmeans_norm, _(
"fix bugs in anscombe transform resulting\n"
3737 "in undersmoothing of the green channel in\n"
3738 "wavelets mode, combined with a bad handling\n"
3739 "of white balance coefficients, and a bug in\n"
3740 "non local means normalization resulting in\n"
3741 "undersmoothing when patch size was increased.\n"
3742 "enabling this option will change the denoising\n"
3743 "you get. once enabled, you won't be able to\n"
3744 "return back to old algorithm."));
3745 gtk_widget_set_tooltip_text(
g->profile, _(
"profile used for variance stabilization"));
3746 gtk_widget_set_tooltip_text(
g->mode, _(
"method used in the denoising core.\n"
3747 "non-local means works best for `lightness' blending,\n"
3748 "wavelets work best for `color' blending"));
3749 gtk_widget_set_tooltip_text(
g->wavelet_color_mode, _(
"color representation used within the algorithm.\n"
3750 "RGB keeps the RGB channels separated,\n"
3751 "while Y0U0V0 combine the channels to\n"
3752 "denoise chroma and luma separately."));
3753 gtk_widget_set_tooltip_text(
g->radius, _(
"radius of the patches to match.\n"
3754 "increase for more sharpness on strong edges, and better denoising of smooth areas.\n"
3755 "if details are oversmoothed, reduce this value or increase the central pixel weight slider."));
3756 gtk_widget_set_tooltip_text(
g->nbhood, _(
"emergency use only: radius of the neighbourhood to search patches in. "
3757 "increase for better denoising performance, but watch the long runtimes! "
3758 "large radii can be very slow. you have been warned"));
3759 gtk_widget_set_tooltip_text(
g->scattering, _(
"scattering of the neighbourhood to search patches in.\n"
3760 "increase for better coarse-grain noise reduction.\n"
3761 "does not affect execution time."));
3762 gtk_widget_set_tooltip_text(
g->central_pixel_weight, _(
"increase the weight of the central pixel\n"
3763 "of the patch in the patch comparison.\n"
3764 "useful to recover details when patch size\n"
3766 gtk_widget_set_tooltip_text(
g->strength, _(
"finetune denoising strength"));
3767 gtk_widget_set_tooltip_text(
g->overshooting, _(
"controls the way parameters are autoset\n"
3768 "increase if shadows are not denoised enough\n"
3769 "or if chroma noise remains.\n"
3770 "this can happen if your picture is underexposed."));
3771 gtk_widget_set_tooltip_text(
g->shadows, _(
"finetune shadows denoising.\n"
3772 "decrease to denoise more aggressively\n"
3773 "dark areas of the image."));
3774 gtk_widget_set_tooltip_text(
g->bias, _(
"correct color cast in shadows.\n"
3775 "decrease if shadows are too purple.\n"
3776 "increase if shadows are too green."));
3777 gtk_widget_set_tooltip_text(
g->use_new_vst, _(
"upgrade the variance stabilizing algorithm.\n"
3778 "new algorithm extends the current one.\n"
3779 "it is more flexible but could give small\n"
3780 "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)
typedef void((*dt_cache_allocate_t)(void *userdata, dt_cache_entry_t *entry))
struct _GtkWidget GtkWidget
GtkWidget, opaque, spelled exactly as GTK spells it.
static dt_aligned_pixel_t rgb
const dt_colormatrix_t dt_aligned_pixel_t out
int dt_conf_get_bool(const char *name)
struct dt_bauhaus_t * dt_bauhaus_get_global(void)
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 dt_noiseprofile_t _default_noise_profile(dt_iop_module_t *module)
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)
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)
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
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)
static dt_iop_gui_data_t * dt_iop_gui_data(const struct dt_iop_module_t *m)
The module's GUI data blob, NULL-safe for headless callers: IOP process() implementations read it for...
#define IOP_GUI_ALLOC(module)
GtkWidget * dt_ui_label_new(const gchar *str)
void dt_print(dt_debug_thread_t thread, const char *msg,...) __attribute__((format(printf
Print to stdout when thread is enabled, prefixed with seconds since startup.
float *const restrict const size_t k
float *const restrict const size_t const size_t ch
#define IS_NULL_PTR(p)
C is way too permissive with !=, == and if(var) checks, which can mean too many things depending on w...
float DT_ALIGNED_ARRAY dt_colormatrix_t[4][4]
#define dt_free_align(ptr)
Release memory from dt_alloc_align() and set ptr to NULL.
static void * dt_calloc_align(size_t size)
dt_alloc_align() followed by a zero fill.
#define dt_free(ptr)
g_free() ptr and set it to NULL, skipping both if it is already NULL.
#define DT_CACHELINE_BYTES
#define DT_MODULE_INTROSPECTION(MODVER, PARAMSTYPE)
DT_MODULE() for a module whose params struct is introspected.
__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)
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)
GtkWidget * dt_ui_notebook_page(GtkNotebook *notebook, const char *text, const char *tooltip)
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)
#define __OMP_SIMD__(...)
#define __OMP_PARALLEL_FOR__(...)
@ DT_DEV_PIXELPIPE_THUMBNAIL
Pixelpipe cache for storing intermediate results in the pixelpipe.
#define dt_pixelpipe_cache_alloc_align(size, pipe)
#define dt_pixelpipe_cache_free_align(mem)
static cairo_surface_t * dt_cairo_image_surface_create(cairo_format_t format, int width, int height)
DT_ALIGNED_PIXEL float dt_aligned_pixel_t[4]
#define for_each_channel(_var,...)
float dt_aligned_pixel_simd_t __attribute__((vector_size(16), aligned(16)))
Apply one channel's tone curve to each of the three colour channels, or pass the channel through unto...
static const dt_aligned_pixel_simd_t sign
const float uint32_t state[4]
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
struct dt_dev_pixelpipe_t * preview_pipe
dt_aligned_pixel_t coeffs
dt_aligned_pixel_t processed_maximum
struct dt_iop_buffer_dsc_t::@56 temperature
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
dt_iop_global_data_t * data
dt_iop_params_t * default_params
struct dt_iop_module_gui_t * gui
struct dt_develop_t * dev
dt_iop_global_data_t * global_data
Region of interest passed through the pixelpipe.
#define __DT_CLONE_TARGETS__