72#include <json-glib/json-glib.h>
96#define USE_NEW_IMPL_CL 0
106#define DT_IOP_DENOISE_PROFILE_INSET DT_PIXEL_APPLY_DPI(5)
107#define DT_IOP_DENOISE_PROFILE_RES 64
108#define DT_IOP_DENOISE_PROFILE_V8_BANDS 5
109#define DT_IOP_DENOISE_PROFILE_BANDS 7
118#define DT_IOP_DENOISE_PROFILE_P_FULCRUM 0.05f
133#define DT_DENOISE_PROFILE_NONE_V9 4
399 const float*
const restrict buf,
const int width,
const int height,
const int scale)
404 snprintf(filename,
sizeof(filename), namespec, scale);
405 FILE *
f = g_fopen(filename,
"wb");
410 for(
size_t k=0;
k<
n;
k++)
411 fwrite(buf+4U*
k,
sizeof(
float), 3,
f);
417#define debug_dump_PFM(p,n,b,w,h,s)
421 void *new_params,
const int new_version)
423 if((old_version == 1 || old_version == 2 || old_version == 3) && new_version == 4)
435 n->radius =
o->radius;
436 n->strength =
o->strength;
437 memcpy(
n->a,
o->a,
sizeof(
float) * 3);
438 memcpy(
n->b,
o->b,
sizeof(
float) * 3);
462 if(!memcmp(interpolated.
a,
o->a,
sizeof(
float) * 3) && !memcmp(interpolated.
b,
o->b,
sizeof(
float) * 3))
469 else if(new_version == 5)
479 memcpy(&v4, old_params,
sizeof(v4));
494 v5->
x[c][b] = v4.
x[c][b];
495 v5->
y[c][b] = v4.
y[c][b];
501 else if(new_version == 6)
507 if(
legacy_params(self, old_params, old_version, &v5, 5))
return 1;
510 memcpy(&v5, old_params,
sizeof(v5));
517 for(
int k = 0;
k < 3;
k++)
526 v6->
x[c][b] = v5.
x[c][b];
527 v6->
y[c][b] = v5.
y[c][b];
533 else if(new_version == 7)
539 if(
legacy_params(self, old_params, old_version, &v6, 6))
return 1;
542 memcpy(&v6, old_params,
sizeof(v6));
548 for(
int k = 0;
k < 3;
k++)
557 v7->
x[c][b] = v6.
x[c][b];
558 v7->
y[c][b] = v6.
y[c][b];
567 else if(new_version == 8)
573 if(
legacy_params(self, old_params, old_version, &v7, 7))
return 1;
576 memcpy(&v7, old_params,
sizeof(v7));
582 for(
int k = 0;
k < 3;
k++)
591 v8->
x[c][b] = v7.
x[c][b];
592 v8->
y[c][b] = v7.
y[c][b];
605 else if(new_version == 9)
611 if(
legacy_params(self, old_params, old_version, &v8, 8))
return 1;
614 memcpy(&v8, old_params,
sizeof(v8));
620 for(
int k = 0;
k < 3;
k++)
650 else if(new_version == 10)
656 if(
legacy_params(self, old_params, old_version, &v9, 9))
return 1;
659 memcpy(&v9, old_params,
sizeof(v9));
670 for(
int k = 0;
k < 3;
k++)
679 v10->
x[c][b] = v9.
x[c][b];
680 v10->
y[c][b] = v9.
y[c][b];
699 else if(new_version == 11)
705 if(
legacy_params(self, old_params, old_version, v11, 10))
return 1;
708 memcpy(v11, old_params,
sizeof(*v11));
714 const float compensate_strength = 2.5f;
715 v11->
strength /= compensate_strength;
725 memset(&
p, 0,
sizeof(
p));
735 p.use_new_vst =
TRUE;
741 p.wb_adaptive_anscombe =
TRUE;
743 p.central_pixel_weight = 0.1f;
744 p.overshooting = 1.0f;
745 p.fix_anscombe_and_nlmeans_norm =
TRUE;
762 return _(
"de_noise (profiled)");
768 _(
"denoise using noise statistics profiled on sensors"),
770 _(
"linear, RGB, scene-referred"),
772 _(
"linear, RGB, scene-referred"));
803 const int P = ceilf(
d->radius * fminf(fminf(roi_in->
scale, 2.0f), 1.0f));
804 const int K = ceilf(
d->nbhood * fminf(fminf(roi_in->
scale, 2.0f), 1.0f));
805 const int K_scattered = ceilf(
d->scattering * (K * K * K + 7.0 * K * sqrt(K)) / 6.0) + K;
807 tiling->factor = 2.0f + 0.25f;
811 tiling->overlap =
P + K_scattered;
819 const float scale = fminf(roi_in->
scale, 1.0f);
822 = fminf(2 * (2u << (max_max_scale - 1)) + 1,
823 fmaxf(
piece->buf_in.height,
piece->buf_in.width) * 0.2f);
824 const float i0 = dt_log2f((supp0 - 1.0f) * .5f);
825 for(; max_scale < max_max_scale; max_scale++)
828 const float supp = 2 * (2u << max_scale) + 1;
830 const float supp_in = supp * (1.0f / scale);
831 const float i_in = dt_log2f((supp_in - 1) * .5f) - 1.0f;
833 const float t = 1.0f - (i_in + .5f) / i0;
837 const int max_filter_radius = (1u << max_scale);
840 tiling->factor_cl = 3.5f + max_scale;
844 tiling->overlap = max_filter_radius;
852static inline void precondition(
const float *
const in,
float *
const buf,
const int wd,
const int ht,
856 = { (b[0] / a[0]) * (b[0] / a[0]) + 3.f / 8.f,
857 (b[1] / a[1]) * (b[1] / a[1]) + 3.f / 8.f,
858 (b[2] / a[2]) * (b[2] / a[2]) + 3.f / 8.f,
860 const size_t npixels = (size_t)wd * ht;
862 for(
size_t j = 0; j < 4U * npixels; j += 4)
866 const float d = fmaxf(0.0f, in[j+c] / a[c] + sigma2_plus_3_8[c]);
867 buf[j+c] = 2.0f * sqrtf(
d);
877 = { (b[0] / a[0]) * (b[0] / a[0]) + 1.f / 8.f,
878 (b[1] / a[1]) * (b[1] / a[1]) + 1.f / 8.f,
879 (b[2] / a[2]) * (b[2] / a[2]) + 1.f / 8.f,
881 const size_t npixels = (size_t)wd * ht;
882 const float sqrt_3_2 = sqrtf(3.0f / 2.0f);
884 for(
size_t j = 0; j < 4U * npixels; j += 4)
888 const float x = buf[j+c], x2 =
x *
x;
890 buf[j+c] = (
x < 0.5f)
892 : a[c] * (1.f / 4.f * x2 + 1.f / 4.f * sqrt_3_2 /
x - 11.f / 8.f / x2
893 + 5.f / 8.f * sqrt_3_2 / (
x * x2) - sigma2_plus_1_8[c]);
925static inline void precondition_v2(
const float *
const in,
float *
const buf,
const int wd,
const int ht,
929 const size_t npixels = (size_t)wd * ht;
932 (-
p[2] + 2) * sqrtf(a), 1.0f };
934 for(
size_t j = 0; j < 4U * npixels; j += 4)
938 buf[j+c] = 2.0f * powf(
MAX(in[j+c] / wb[c] + b, 0.0f), expon[c]) / denom[c];
1003static inline void backtransform_v2(
float *
const buf,
const int wd,
const int ht,
const float a,
1007 const size_t npixels = (size_t)wd * ht;
1009 1.0f / (1.0f -
p[2] / 2.0f), 1.0f };
1010 const dt_aligned_pixel_t denom = { 4.0f / (sqrtf(a) * (2.0f -
p[0])), 4.0f / (sqrtf(a) * (2.0f -
p[1])),
1011 4.0f / (sqrtf(a) * (2.0f -
p[2])), 1.0f };
1013 for(
size_t j = 0; j < 4U * npixels; j += 4)
1017 const float x =
MAX(buf[j+c], 0.0f);
1018 const float delta =
x *
x + bias;
1019 const float z1 = (
x + sqrtf(
MAX(
delta, 0.0f))) / denom[c];
1020 buf[j+c] = wb[c] * (powf(z1, expon[c]) - b);
1032 2.0f / ((-
p[1] + 2) * sqrtf(a)),
1033 2.0f / ((-
p[2] + 2) * sqrtf(a)),
1036 for(
size_t j = 0; j < (size_t)4 * ht * wd; j += 4)
1041 tmp[c] = powf(
MAX(in[j+c] + b, 0.0f), expon[c]) * scale[c];
1043 for(
int c = 0; c < 3; c++)
1048 sum += toY0U0V0[c][
k] * tmp[
k];
1061 const dt_aligned_pixel_t bias_wb = { bias * wb[0], bias * wb[1], bias * wb[2], 0.0f };
1063 1.0f / (1.0f -
p[1] / 2.0f),
1064 1.0f / (1.0f -
p[2] / 2.0f),
1067 (sqrtf(a) * (2.0f -
p[1])) / 4.0f,
1068 (sqrtf(a) * (2.0f -
p[2])) / 4.0f,
1071 for(
size_t j = 0; j < (size_t)4 * ht * wd; j += 4)
1074 for(
int k = 0;
k < 3;
k++)
1078 rgb[
k] += toRGB[
k][c] * buf[j+c];
1083 const float x =
MAX(
rgb[c], 0.0f);
1084 const float delta =
x *
x + bias_wb[c];
1085 const float z1 = (
x + sqrtf(
MAX(
delta, 0.0f))) * scale[c];
1086 buf[j+c] = powf(z1, expon[c]) - b;
1101 const float wb_mean = (
piece->dsc_in.temperature.coeffs[0] +
piece->dsc_in.temperature.coeffs[1]
1102 +
piece->dsc_in.temperature.coeffs[2])
1106 wb[0] = wb[1] = wb[2] = wb[3] = wb_mean;
1107 if(
d->fix_anscombe_and_nlmeans_norm)
1109 if(wb_mean != 0.0f &&
d->wb_adaptive_anscombe)
1111 for(
int i = 0;
i < 3;
i++) wb[
i] =
piece->dsc_in.temperature.coeffs[
i];
1113 else if(wb_mean == 0.0f)
1126 wb[
i] = weights[
i] *
piece->dsc_in.processed_maximum[
i];
1136 const float biga = in[1][1] * in[2][2] - in[1][2] * in[2][1];
1137 const float bigb = -in[1][0] * in[2][2] + in[1][2] * in[2][0];
1138 const float bigc = in[1][0] * in[2][1] - in[1][1] * in[2][0];
1139 const float bigd = -in[0][1] * in[2][2] + in[0][2] * in[2][1];
1140 const float bige = in[0][0] * in[2][2] - in[0][2] * in[2][0];
1141 const float bigf = -in[0][0] * in[2][1] + in[0][1] * in[2][0];
1142 const float bigg = in[0][1] * in[1][2] - in[0][2] * in[1][1];
1143 const float bigh = -in[0][0] * in[1][2] + in[0][2] * in[1][0];
1144 const float bigi = in[0][0] * in[1][1] - in[0][1] * in[1][0];
1146 const float det = in[0][0] * biga + in[0][1] * bigb + in[0][2] * bigc;
1152 out[0][0] = 1.0f / det * biga;
1153 out[0][1] = 1.0f / det * bigd;
1154 out[0][2] = 1.0f / det * bigg;
1156 out[1][0] = 1.0f / det * bigb;
1157 out[1][1] = 1.0f / det * bige;
1158 out[1][2] = 1.0f / det * bigh;
1160 out[2][0] = 1.0f / det * bigc;
1161 out[2][1] = 1.0f / det * bigf;
1162 out[2][2] = 1.0f / det * bigi;
1179 float sum_invwb = 1.0f/wb[0] + 1.0f/wb[1] + 1.0f/wb[2];
1189 sum_invwb *= sqrtf(3);
1190 toY0U0V0[0][0] = sum_invwb / wb[0];
1191 toY0U0V0[0][1] = sum_invwb / wb[1];
1192 toY0U0V0[0][2] = sum_invwb / wb[2];
1193 toY0U0V0[0][3] = 0.0f;
1200 const float stddevU0 = sqrtf(0.5f * 0.5f * wb[0] * wb[0] + 0.5f * 0.5f * wb[2] * wb[2]);
1201 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]);
1202 toY0U0V0[1][0] /= stddevU0;
1203 toY0U0V0[1][1] /= stddevU0;
1204 toY0U0V0[1][2] /= stddevU0;
1205 toY0U0V0[1][3] = 0.0f;
1206 toY0U0V0[2][0] /= stddevV0;
1207 toY0U0V0[2][1] /= stddevV0;
1208 toY0U0V0[2][2] /= stddevV0;
1209 toY0U0V0[2][3] = 0.0f;
1210 const gboolean is_invertible = invert_matrix(toY0U0V0, toRGB);
1214 float stddevY0 = sqrtf(1.0f / 9.0f * (wb[0] * wb[0] + wb[1] * wb[1] + wb[2] * wb[2]));
1215 toY0U0V0[0][0] = 1.0f / (3.0f * stddevY0);
1216 toY0U0V0[0][1] = 1.0f / (3.0f * stddevY0);
1217 toY0U0V0[0][2] = 1.0f / (3.0f * stddevY0);
1218 toY0U0V0[0][3] = 0.0f;
1219 invert_matrix(toY0U0V0, toRGB);
1227 const float sigma = 1.0f;
1229 const float varf = sqrtf(2.0f + 2.0f * 4.0f * 4.0f + 6.0f * 6.0f) / 16.0f;
1230 const float sigma_band = powf(varf, scale) *
sigma;
1232 const float sb2 = sigma_band * sigma_band;
1233 const dt_aligned_pixel_t var_y = { sum_y2[0] / (npixels - 1.0f), sum_y2[1] / (npixels - 1.0f),
1234 sum_y2[2] / (npixels - 1.0f), 0.0f };
1236 sqrtf(
MAX(1e-6f, var_y[2] - sb2)), 1.0f };
1251 float band_force_exp_2
1253 band_force_exp_2 *= band_force_exp_2;
1254 band_force_exp_2 *= 4;
1257 adjt[
ch] *= band_force_exp_2;
1260 band_force_exp_2 *= band_force_exp_2;
1261 band_force_exp_2 *= 4;
1262 adjt[0] *= band_force_exp_2;
1264 band_force_exp_2 *= band_force_exp_2;
1265 band_force_exp_2 *= 4;
1266 adjt[1] *= band_force_exp_2;
1268 band_force_exp_2 *= band_force_exp_2;
1269 band_force_exp_2 *= 4;
1270 adjt[2] *= band_force_exp_2;
1275 band_force_exp_2 *= band_force_exp_2;
1276 band_force_exp_2 *= 4;
1277 adjt[0] *= band_force_exp_2;
1279 band_force_exp_2 *= band_force_exp_2;
1280 band_force_exp_2 *= 4;
1281 adjt[1] *= band_force_exp_2;
1282 adjt[2] *= band_force_exp_2;
1285 thrs[
c] = adjt[
c] * sb2 / std_x[
c];
1292 const dt_iop_roi_t *
const roi_out,
const eaw_dn_decompose_t decompose,
1293 const eaw_synthesize_t synthesize)
1299#define MAX_MAX_SCALE DT_IOP_DENOISE_PROFILE_BANDS
1302 const float in_scale = fminf(roi_in->
scale, 1.0f);
1306 const float i0 = dt_log2f((supp0 - 1.0f) * .5f);
1310 const float supp = 2 * (2u << max_scale) + 1;
1312 const float supp_in = supp * (1.0f / in_scale);
1313 const float i_in = dt_log2f((supp_in - 1) * .5f) - 1.0f;
1315 const float t = 1.0f - (i_in + .5f) / i0;
1319 const int max_mult = 1u << (max_scale - 1);
1322 const float *
const restrict in = (
const float*)ivoid;
1323 float *
const restrict
out = (
float*)
ovoid;
1329 memcpy(
out, in,
sizeof(
float) * 4 * npixels);
1334 float *restrict precond = NULL;
1335 float *restrict tmp = NULL;
1349 MAX(
d->shadows + 0.1 * logf(in_scale / wb[1]), 0.0f),
1350 MAX(
d->shadows + 0.1 * logf(in_scale / wb[2]), 0.0f),
1357 { 0.5f, 0.0f, -0.5f },
1358 { 0.25f, -0.5f, 0.25f } };
1360 { 0.0f, 0.0f, 0.0f },
1361 { 0.0f, 0.0f, 0.0f } };
1366 const float compensate_strength = (
d->wavelet_color_mode ==
MODE_RGB) ? 1.0f : 2.5f;
1368 for(
size_t k = 0;
k < 3;
k++)
1371 toY0U0V0[
k][c] /= (
d->strength * compensate_strength * in_scale);
1372 toRGB[
k][c] *= (
d->strength * compensate_strength * in_scale);
1384 else if(
d->wavelet_color_mode ==
MODE_RGB)
1395 float *restrict buf1 = precond;
1396 float *restrict buf2 = tmp;
1399 memset(
out, 0,
sizeof(
float) * 4 * npixels);
1401 for(
int scale = 0; scale < max_scale; scale++)
1411 const float sigma = 1.0f;
1412 const float varf = sqrtf(2.0f + 2.0f * 4.0f * 4.0f + 6.0f * 6.0f) / 16.0f;
1413 const float sigma_band = powf(varf, scale) *
sigma;
1415 decompose(buf2, buf1, buf, sum_y2, scale, 1.0f / (sigma_band * sigma_band),
width,
height);
1421 variance_stabilizing_xform(
thrs, scale, max_scale, npixels, sum_y2,
d);
1431 for (
size_t k = 0;
k < 4U * npixels;
k++)
1438 else if(
d->wavelet_color_mode ==
MODE_RGB)
1457#if defined(HAVE_OPENCL) && !USE_NEW_IMPL_CL
1460 return (a > 0) - (a < 0);
1472 float norm = .045f / ((2 *
P + 1) * (2 *
P + 1));
1473 if(!
d->fix_anscombe_and_nlmeans_norm)
1476 norm = .015f / (2 *
P + 1);
1488 float scattering =
d->scattering;
1494 const int maxk = (K * K * K + 7.0 * K * sqrt(K)) * scattering / 6.0 + K;
1496 scattering = (maxk - K) * 6.0 / (K * K * K + 7.0 * K * sqrt(K));
1501 const int maxk = (K * K * K + 7.0 * K * sqrt(K)) * scattering / 6.0 + K;
1502 K =
MAX(
MIN(4, K), K * scale);
1503 scattering = (maxk - K) * 6.0 / (K * K * K + 7.0 * K * sqrt(K));
1513 const void *
const ivoid,
const dt_iop_roi_t *
const roi_in,
1522 p[0] =
MAX(
d->shadows + 0.1 * logf(scale / wb[0]), 0.0f);
1523 p[1] =
MAX(
d->shadows + 0.1 * logf(scale / wb[1]), 0.0f);
1524 p[2] =
MAX(
d->shadows + 0.1 * logf(scale / wb[2]), 0.0f);
1530 wb[
i] *=
d->strength * scale;
1532 aa[
i] =
d->a[1] * wb[
i];
1533 bb[
i] =
d->b[1] * wb[
i];
1544 return compensate_p;
1561 p[0] =
MAX(
d->shadows + 0.1 * logf(scale / wb[0]), 0.0f);
1562 p[1] =
MAX(
d->shadows + 0.1 * logf(scale / wb[1]), 0.0f);
1563 p[2] =
MAX(
d->shadows + 0.1 * logf(scale / wb[2]), 0.0f);
1569 wb[
i] *=
d->strength * scale;
1571 aa[
i] =
d->a[1] * wb[
i];
1572 bb[
i] =
d->b[1] * wb[
i];
1581 aa[c] =
d->a[1] * compensate_p;
1585 return compensate_p;
1610 int (*denoiser)(
const float *
const inbuf,
float *
const outbuf,
1623 const float scale = fminf(fminf(roi_in->
scale, 2.0f), 1.0f);
1624 const int P = ceilf(
d->radius * scale);
1626 const float scattering = nlmeans_scattering(
pipe, &K,
d,
piece, scale);
1627 const float norm = nlmeans_norm(
P,
d);
1628 const float central_pixel_weight =
d->central_pixel_weight * scale;
1635 const float compensate_p = nlmeans_precondition(
d,
piece,wb,ivoid,roi_in,scale,in,aa,bb,
p);
1642 .center_weight = central_pixel_weight,
1649 const int err = denoiser(in,
ovoid,roi_in,roi_out,&
params);
1653 nlmeans_backtransform(
d,
ovoid,roi_in,scale,compensate_p,wb,aa,bb,
p);
1668static void sum_rec(
const size_t npixels,
const float *in,
float *
out)
1676 for(
size_t i = 0;
i < npixels;
i++)
1680 out[c] += in[
i * 4 + c];
1686 const size_t npixels_first_half = npixels >> 1;
1687 const size_t npixels_second_half = npixels - npixels_first_half;
1689 sum_rec(npixels_second_half, in + 4U * npixels_first_half,
out + 4U * npixels_first_half);
1692 out[c] +=
out[4U * npixels_first_half + c];
1706 for(
size_t i = 0;
i < npixels;
i++)
1710 const float diff = in[
i * 4 + c] - mean[c];
1711 out[c] += diff * diff;
1717 const size_t npixels_first_half = npixels >> 1;
1718 const size_t npixels_second_half = npixels - npixels_first_half;
1720 variance_rec(npixels_second_half, in + 4U * npixels_first_half,
out + 4U * npixels_first_half, mean);
1723 out[c] +=
out[4U * npixels_first_half + c];
1738 memcpy(
ovoid, ivoid,
sizeof(
float) * 4 * npixels);
1754 MAX(
d->shadows - 0.1 * logf(wb[1]), 0.0f),
1755 MAX(
d->shadows - 0.1 * logf(wb[2]), 0.0f),
1771 mean[
c] =
out[
c] / npixels;
1777 var[
c] =
out[
c] / (npixels - 1);
1779 g->variance_R = var[0];
1780 g->variance_G = var[1];
1781 g->variance_B = var[2];
1783 memcpy(
ovoid, ivoid,
sizeof(
float) * 4 * npixels);
1787#if defined(HAVE_OPENCL) && !USE_NEW_IMPL_CL
1790 unsigned int current = *
state;
1791 unsigned int next = (current >=
max - 1 ? 0 : current + 1);
1799#if defined(HAVE_OPENCL)
1812 const float scale = fminf(fminf(roi_in->
scale, 2.0f), 1.0f);
1813 const int P = ceilf(
d->radius * scale);
1815 const float scattering = nlmeans_scattering(
pipe, &K,
d,
piece, scale);
1816 const float norm = nlmeans_norm(
P,
d);
1817 const float central_pixel_weight =
d->central_pixel_weight * scale;
1835 const float sigma2[4] = { (bb[0] / aa[0]) * (bb[0] / aa[0]), (bb[1] / aa[1]) * (bb[1] / aa[1]),
1836 (bb[2] / aa[2]) * (bb[2] / aa[2]), 0.0f };
1865 if (err == CL_SUCCESS)
1870 .scattering = scattering,
1874 .center_weight = central_pixel_weight,
1889 if (err == CL_SUCCESS)
1904 const float bias =
d->bias - 0.5 * logf(scale);
1920 if (err == CL_SUCCESS)
1931 const float scale = fminf(fminf(roi_in->
scale, 2.0f), 1.0f);
1932 const int P = ceilf(
d->radius * scale);
1934 const float scattering = nlmeans_scattering(
pipe, &K,
d,
piece, scale);
1935 const float norm = nlmeans_norm(
P,
d);
1936 const float central_pixel_weight =
d->central_pixel_weight * scale;
1944 const dt_aligned_pixel_t sigma2 = { (bb[0] / aa[0]) * (bb[0] / aa[0]), (bb[1] / aa[1]) * (bb[1] / aa[1]),
1945 (bb[2] / aa[2]) * (bb[2] / aa[2]), 0.0f };
1955 unsigned int state = 0;
1959 if(buckets[
k] == NULL)
goto error;
1965 .cellsize =
sizeof(float), .overhead = 0,
1966 .sizex = 1u << 16, .sizey = 1 };
1969 hblocksize = hlocopt.
sizex;
1976 .cellsize =
sizeof(float), .overhead = 0,
1977 .sizex = 1, .sizey = 1u << 16 };
1980 vblocksize = vlocopt.
sizey;
1998 if(err != CL_SUCCESS)
goto error;
2011 if(err != CL_SUCCESS)
goto error;
2018 if(err != CL_SUCCESS)
goto error;
2023 for(
int kj_index = -K; kj_index <= 0; kj_index++)
2025 for(
int ki_index = -K; ki_index <= K; ki_index++)
2036 const int abs_kj = abs(kj_index);
2037 const int abs_ki = abs(ki_index);
2038 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);
2039 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);
2040 int q[2] = {
i, j };
2049 if(err != CL_SUCCESS)
goto error;
2054 local[0] = hblocksize;
2067 if(err != CL_SUCCESS)
goto error;
2070 sizesl[1] = bheight;
2073 local[1] = vblocksize;
2086 (
void *)¢ral_pixel_weight);
2089 if(err != CL_SUCCESS)
goto error;
2099 if(err != CL_SUCCESS)
goto error;
2113 if(err != CL_SUCCESS)
goto error;
2117 const float bias =
d->bias - 0.5 * logf(scale);
2129 if(err != CL_SUCCESS)
goto error;
2148 if(err != CL_SUCCESS)
dt_print(
DT_DEBUG_OPENCL,
"[opencl_denoiseprofile] couldn't enqueue kernel! %d\n", err);
2163 const float scale = fminf(roi_in->
scale, 1.0f);
2166 =
MIN(2 * (2u << (max_max_scale - 1)) + 1,
2168 const float i0 = dt_log2f((supp0 - 1.0f) * .5f);
2169 for(; max_scale < max_max_scale; max_scale++)
2172 const float supp = 2 * (2u << max_scale) + 1;
2174 const float supp_in = supp * (1.0f / scale);
2175 const float i_in = dt_log2f((supp_in - 1) * .5f) - 1.0f;
2177 const float t = 1.0f - (i_in + .5f) / i0;
2187 cl_mem dev_tmp = NULL;
2188 cl_mem dev_buf1 = NULL;
2189 cl_mem dev_buf2 = NULL;
2190 cl_mem dev_m = NULL;
2191 cl_mem dev_r = NULL;
2192 cl_mem dev_filter = NULL;
2193 cl_mem *dev_detail = calloc(max_max_scale,
sizeof(cl_mem));
2194 float *sumsum = NULL;
2201 size_t origin[] = { 0, 0, 0 };
2204 if(err != CL_SUCCESS)
goto error;
2211 .cellsize = 4 *
sizeof(float), .overhead = 0,
2212 .sizex = 1u << 4, .sizey = 1u << 4 };
2220 const int bufsize = (bwidth / flocopt.
sizex) * (bheight / flocopt.
sizey);
2224 .cellsize = 4 *
sizeof(float), .overhead = 0,
2225 .sizex = 1u << 16, .sizey = 1 };
2245 float m[] = { 0.0625f, 0.25f, 0.375f, 0.25f, 0.0625f };
2247 for(
int j = 0; j < 5; j++)
2248 for(
int i = 0;
i < 5;
i++) mm[j][
i] =
m[
i] *
m[j];
2253 for(
int k = 0;
k < max_scale;
k++)
2256 if(dev_detail[
k] == NULL)
goto error;
2266 MAX(
d->shadows + 0.1 * logf(scale / wb[1]), 0.0f),
2267 MAX(
d->shadows + 0.1 * logf(scale / wb[2]), 0.0f), 1.0f};
2271 { 0.5f, 0.0f, -0.5f },
2272 { 0.25f, -0.5f, 0.25f } };
2274 { 0.0f, 0.0f, 0.0f },
2275 { 0.0f, 0.0f, 0.0f } };
2280 const float compensate_strength = (
d->wavelet_color_mode ==
MODE_RGB) ? 1.0f : 2.5f;
2285 for(
size_t k = 0;
k < 3;
k++)
2286 for(
size_t c = 0; c < 3; c++)
2289 toRGB[3*
k+c] = toRGB_tmp[
k][c] *
d->strength * compensate_strength * scale;
2290 toY0U0V0[3*
k+c] = toY0U0V0_tmp[
k][c] / (
d->strength * compensate_strength * scale);
2298 const dt_aligned_pixel_t sigma2 = { (bb[0] / aa[0]) * (bb[0] / aa[0]), (bb[1] / aa[1]) * (bb[1] / aa[1]),
2299 (bb[2] / aa[2]) * (bb[2] / aa[2]), 0.0f };
2305 aa[c] =
d->a[1] * compensate_p;
2321 if(err != CL_SUCCESS)
goto error;
2323 else if(
d->wavelet_color_mode ==
MODE_RGB)
2334 if(err != CL_SUCCESS)
goto error;
2338 cl_mem dev_Y0U0V0 = NULL;
2352 if(err != CL_SUCCESS)
goto error;
2365 for(
int s = 0; s < max_scale; s++)
2367 const float sigma = 1.0f;
2368 const float varf = sqrtf(2.0f + 2.0f * 4.0f * 4.0f + 6.0f * 6.0f) / 16.0f;
2369 const float sigma_band = powf(varf, s) *
sigma;
2370 const float inv_sigma2 = 1.0f / (sigma_band * sigma_band);
2375 (
void *)&dev_detail[s]);
2381 (
void *)&inv_sigma2);
2383 (
void *)&dev_filter);
2385 if(err != CL_SUCCESS)
goto error;
2388 cl_mem dev_buf3 = dev_buf2;
2389 dev_buf2 = dev_buf1;
2390 dev_buf1 = dev_buf3;
2394 for(
int s = max_scale - 1; s >= 0; s--)
2397 const float sigma = 1.0f;
2399 const float varf = sqrtf(2.0f + 2.0f * 4.0f * 4.0f + 6.0f * 6.0f) / 16.0f;
2400 const float sigma_band = powf(varf, s) *
sigma;
2409 lsizes[1] = bheight;
2411 llocal[0] = flocopt.
sizex;
2412 llocal[1] = flocopt.
sizey;
2420 sizeof(
float) * 4 * flocopt.
sizex * flocopt.
sizey, NULL);
2423 if(err != CL_SUCCESS)
goto error;
2426 lsizes[0] = (size_t)reducesize * slocopt.
sizex;
2429 llocal[0] = slocopt.
sizex;
2439 if(err != CL_SUCCESS)
goto error;
2442 sizeof(
float) * 4 * reducesize, CL_TRUE);
2443 if(err != CL_SUCCESS)
2446 for(
int k = 0;
k < reducesize;
k++)
2450 sum_y2[c] += sumsum[4 *
k + c];
2454 const float sb2 = sigma_band * sigma_band;
2455 const dt_aligned_pixel_t var_y = { sum_y2[0] / (npixels - 1.0f), sum_y2[1] / (npixels - 1.0f),
2456 sum_y2[2] / (npixels - 1.0f), 0.0f };
2458 sqrtf(
MAX(1e-6f, var_y[2] - sb2)), 1.0f };
2474 band_force_exp_2 *= band_force_exp_2;
2475 band_force_exp_2 *= 4;
2478 adjt[
ch] *= band_force_exp_2;
2481 band_force_exp_2 *= band_force_exp_2;
2482 band_force_exp_2 *= 4;
2483 adjt[0] *= band_force_exp_2;
2485 band_force_exp_2 *= band_force_exp_2;
2486 band_force_exp_2 *= 4;
2487 adjt[1] *= band_force_exp_2;
2489 band_force_exp_2 *= band_force_exp_2;
2490 band_force_exp_2 *= 4;
2491 adjt[2] *= band_force_exp_2;
2496 band_force_exp_2 *= band_force_exp_2;
2497 band_force_exp_2 *= 4;
2498 adjt[0] *= band_force_exp_2;
2500 band_force_exp_2 *= band_force_exp_2;
2501 band_force_exp_2 *= 4;
2502 adjt[1] *= band_force_exp_2;
2503 adjt[2] *= band_force_exp_2;
2507 adjt[2] * sb2 / std_x[2], 0.0f };
2515 (
void *)&dev_detail[s]);
2532 if(err != CL_SUCCESS)
goto error;
2535 cl_mem dev_buf3 = dev_buf2;
2536 dev_buf2 = dev_buf1;
2537 dev_buf1 = dev_buf3;
2542 if(dev_buf1 != dev_tmp)
2544 size_t origin[] = { 0, 0, 0 };
2547 if(err != CL_SUCCESS)
goto error;
2559 if(err != CL_SUCCESS)
goto error;
2561 else if(
d->wavelet_color_mode ==
MODE_RGB)
2563 const float bias =
d->bias - 0.5 * logf(scale);
2574 if(err != CL_SUCCESS)
goto error;
2578 cl_mem dev_RGB = NULL;
2582 const float bias =
d->bias - 0.5 * logf(scale);
2595 if(err != CL_SUCCESS)
goto error;
2608 for(
int k = 0;
k < max_scale;
k++)
2619 for(
int k = 0;
k < max_scale;
k++)
2657 err = process_nlmeans(
pipe,
piece, ivoid,
ovoid, roi_in, roi_out);
2661 err = process_variance(self,
pipe,
piece, ivoid,
ovoid, roi_in, roi_out);
2667 return MIN((
unsigned)(1.0f + a * 15000.0f + a * a * 300000.0f), 8);
2672 return MIN(3000.0f * a, 1.0f);
2677 return MIN(
MAX(0.1f - 0.1 * logf(a), 0.7f), 1.8f);
2682 return -
MAX(5 + 0.5 * logf(a), 0.0);
2710 const int iso =
module->dev->image_storage.exif_iso;
2712 for(GList *iter = profiles; iter; iter = g_list_next(iter))
2715 if(current->
iso == iso)
2717 interpolated = *current;
2718 interpolated.
a[0] = -1.0f;
2721 if(last && last->
iso < iso && current->
iso > iso)
2723 interpolated.
iso = iso;
2725 interpolated.
a[0] = -1.0f;
2731 return interpolated;
2742 const float a = interpolated.
a[1];
2750 for(
int k = 0;
k < 3;
k++)
2752 d->a[
k] = interpolated.
a[
k];
2753 d->b[
k] = interpolated.
b[
k];
2759 const int program = 11;
2810 for(GList *iter = profiles; iter; iter = g_list_next(iter))
2813 if(current->
iso == iso)
2815 interpolated = *current;
2818 if(last && last->
iso < iso && current->
iso > iso)
2820 interpolated.
iso = iso;
2828 return interpolated;
2838 d->nbhood =
p->nbhood;
2839 d->central_pixel_weight =
p->central_pixel_weight;
2840 d->strength =
p->strength;
2841 d->overshooting =
p->overshooting;
2842 for(
int i = 0;
i < 3;
i++)
2848 d->wavelet_color_mode =
p->wavelet_color_mode;
2857 for(
int k = 0;
k < 3;
k++)
2859 d->a[
k] = interpolated.
a[
k];
2860 d->b[
k] = interpolated.
b[
k];
2866 const float gain =
p->overshooting;
2874 d->radius =
p->radius;
2875 d->scattering =
p->scattering;
2876 d->shadows =
p->shadows;
2890 d->wb_adaptive_anscombe =
p->wb_adaptive_anscombe;
2891 d->fix_anscombe_and_nlmeans_norm =
p->fix_anscombe_and_nlmeans_norm;
2892 d->use_new_vst =
p->use_new_vst;
2934 for(
int k = 0;
k < 3;
k++)
2936 p->
a[
k] = profile->
a[
k];
2937 p->b[
k] = profile->
b[
k];
2951 gtk_widget_hide(
g->box_wavelets);
2952 gtk_widget_hide(
g->box_variance);
2953 gtk_widget_show_all(
g->box_nlm);
2957 gtk_widget_hide(
g->box_wavelets);
2958 gtk_widget_hide(
g->box_variance);
2959 gtk_widget_show_all(
g->box_nlm);
2960 gtk_widget_set_visible(
g->radius,
FALSE);
2961 gtk_widget_set_visible(
g->nbhood,
FALSE);
2962 gtk_widget_set_visible(
g->scattering,
FALSE);
2966 gtk_widget_hide(
g->box_nlm);
2967 gtk_widget_hide(
g->box_variance);
2968 gtk_widget_show_all(
g->box_wavelets);
2969 gtk_widget_set_visible(GTK_WIDGET(
g->wavelet_color_mode),
p->use_new_vst);
2970 gtk_widget_set_visible(GTK_WIDGET(
g->channel_tabs),
p->use_new_vst && (
p->wavelet_color_mode ==
MODE_RGB));
2971 gtk_widget_set_visible(GTK_WIDGET(
g->channel_tabs_Y0U0V0),
p->use_new_vst && (
p->wavelet_color_mode ==
MODE_Y0U0V0));
2975 gtk_widget_hide(
g->box_nlm);
2976 gtk_widget_hide(
g->box_variance);
2977 gtk_widget_show_all(
g->box_wavelets);
2978 gtk_widget_set_visible(GTK_WIDGET(
g->wavelet_color_mode),
p->use_new_vst);
2979 gtk_widget_set_visible(GTK_WIDGET(
g->channel_tabs),
p->use_new_vst && (
p->wavelet_color_mode ==
MODE_RGB));
2980 gtk_widget_set_visible(GTK_WIDGET(
g->channel_tabs_Y0U0V0),
p->use_new_vst && (
p->wavelet_color_mode ==
MODE_Y0U0V0));
2984 gtk_widget_hide(
g->box_wavelets);
2985 gtk_widget_hide(
g->box_nlm);
2986 gtk_widget_show_all(
g->box_variance);
2990 gtk_widget_set_visible(
g->shadows,
p->use_new_vst && !auto_mode);
2991 gtk_widget_set_visible(
g->bias,
p->use_new_vst && !auto_mode);
2992 gtk_widget_set_visible(
g->overshooting, auto_mode);
3001 if(w ==
g->wavelet_color_mode)
3003 gtk_widget_set_visible(GTK_WIDGET(
g->channel_tabs), (
p->wavelet_color_mode ==
MODE_RGB));
3004 gtk_widget_set_visible(GTK_WIDGET(
g->channel_tabs_Y0U0V0), (
p->wavelet_color_mode ==
MODE_Y0U0V0));
3010 else if(w ==
g->overshooting)
3012 const float gain =
p->overshooting;
3017 a = interpolated.
a[1];
3023 gtk_widget_set_visible(
g->radius,
TRUE);
3024 gtk_widget_set_visible(
g->scattering,
TRUE);
3027 gtk_widget_set_visible(
g->radius,
FALSE);
3028 gtk_widget_set_visible(
g->scattering,
FALSE);
3034 gtk_widget_show_all(
g->box_nlm);
3037 gtk_widget_hide(
g->box_nlm);
3039 gtk_widget_set_visible(
g->shadows,
TRUE);
3040 gtk_widget_set_visible(
g->bias,
TRUE);
3043 gtk_widget_set_visible(
g->shadows,
FALSE);
3044 gtk_widget_set_visible(
g->bias,
FALSE);
3046 else if(w ==
g->use_new_vst)
3049 gtk_widget_set_visible(
g->shadows,
p->use_new_vst && !auto_mode);
3050 gtk_widget_set_visible(
g->bias,
p->use_new_vst && !auto_mode);
3051 gtk_widget_set_visible(
g->wavelet_color_mode,
p->use_new_vst);
3074 g_strlcpy(
name, _(
g->interpolated.name),
sizeof(
name));
3078 for(GList *iter =
g->profiles; iter; iter = g_list_next(iter))
3081 if(current->
iso == iso)
3083 g->interpolated = *current;
3084 g->interpolated.
a[0] = -1.0f;
3085 snprintf(
name,
sizeof(
name), _(
"found match for ISO %d"), iso);
3088 if(last && last->
iso < iso && current->
iso > iso)
3090 g->interpolated.iso = iso;
3092 g->interpolated.a[0] = -1.0f;
3093 snprintf(
name,
sizeof(
name), _(
"interpolated from ISO %d and %d"), last->
iso, current->
iso);
3099 for(GList *iter =
g->profiles; iter; iter = g_list_next(iter))
3113 unsigned combobox_index = 0;
3118 gtk_widget_hide(
g->box_wavelets);
3119 gtk_widget_hide(
g->box_variance);
3120 gtk_widget_show_all(
g->box_nlm);
3124 gtk_widget_hide(
g->box_wavelets);
3125 gtk_widget_hide(
g->box_variance);
3126 gtk_widget_show_all(
g->box_nlm);
3127 gtk_widget_set_visible(
g->radius,
FALSE);
3128 gtk_widget_set_visible(
g->nbhood,
FALSE);
3129 gtk_widget_set_visible(
g->scattering,
FALSE);
3133 gtk_widget_hide(
g->box_nlm);
3134 gtk_widget_hide(
g->box_variance);
3135 gtk_widget_show_all(
g->box_wavelets);
3139 gtk_widget_hide(
g->box_nlm);
3140 gtk_widget_hide(
g->box_variance);
3141 gtk_widget_show_all(
g->box_wavelets);
3145 gtk_widget_hide(
g->box_wavelets);
3146 gtk_widget_hide(
g->box_nlm);
3147 gtk_widget_show_all(
g->box_variance);
3158 a = interpolated.
a[1];
3162 const float gain =
p->overshooting;
3176 for(GList *iter =
g->profiles; iter; iter = g_list_next(iter),
i++)
3179 if(!memcmp(profile->
a,
p->a,
sizeof(
float) * 3)
3180 && !memcmp(profile->
b,
p->b,
sizeof(
float) * 3))
3187 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(
g->wb_adaptive_anscombe),
p->wb_adaptive_anscombe);
3188 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(
g->fix_anscombe_and_nlmeans_norm),
p->fix_anscombe_and_nlmeans_norm);
3189 gtk_widget_set_visible(
g->fix_anscombe_and_nlmeans_norm, !
p->fix_anscombe_and_nlmeans_norm);
3190 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(
g->use_new_vst),
p->use_new_vst);
3191 gtk_widget_set_visible(
g->use_new_vst, !
p->use_new_vst);
3194 gtk_widget_set_visible(
g->overshooting, auto_mode);
3195 gtk_widget_set_visible(
g->wavelet_color_mode,
p->use_new_vst && wavelet_mode);
3196 gtk_widget_set_visible(
g->shadows,
p->use_new_vst && !auto_mode);
3197 gtk_widget_set_visible(
g->bias,
p->use_new_vst && !auto_mode);
3198 gtk_widget_set_visible(GTK_WIDGET(
g->channel_tabs), (
p->wavelet_color_mode ==
MODE_RGB));
3199 gtk_widget_set_visible(GTK_WIDGET(
g->channel_tabs_Y0U0V0), (
p->wavelet_color_mode ==
MODE_Y0U0V0));
3208 gtk_notebook_set_current_page(GTK_NOTEBOOK(
g->channel_tabs),
g->channel);
3224 gtk_notebook_set_current_page(GTK_NOTEBOOK(
g->channel_tabs),
g->channel);
3226 gtk_widget_set_visible(
g->fix_anscombe_and_nlmeans_norm, !
p->fix_anscombe_and_nlmeans_norm);
3227 gtk_widget_set_visible(
g->use_new_vst, !
p->use_new_vst);
3231 const double mouse_y,
const float rad)
3235 const float f = expf(-(mouse_x -
p->x[
ch][
k]) * (mouse_x -
p->x[
ch][
k]) / (rad * rad));
3236 p->y[
ch][
k] = (1 -
f) *
p->y[
ch][
k] +
f * mouse_y;
3247 if(!isnan(c->variance_R))
3249 gchar *str = g_strdup_printf(
"%.2f", c->variance_R);
3251 gtk_label_set_text(c->label_var_R, str);
3255 if(!isnan(c->variance_G))
3257 gchar *str = g_strdup_printf(
"%.2f", c->variance_G);
3259 gtk_label_set_text(c->label_var_G, str);
3263 if(!isnan(c->variance_B))
3265 gchar *str = g_strdup_printf(
"%.2f", c->variance_B);
3267 gtk_label_set_text(c->label_var_B, str);
3280 int ch = (int)c->channel;
3288 GtkAllocation allocation;
3289 gtk_widget_get_allocation(widget, &allocation);
3290 int width = allocation.width,
height = allocation.height;
3292 cairo_t *cr = cairo_create(cst);
3293 cairo_set_source_rgb(cr, .2, .2, .2);
3297 cairo_translate(cr, inset, inset);
3302 cairo_set_source_rgb(cr, .1, .1, .1);
3306 cairo_set_source_rgb(cr, .3, .3, .3);
3312 cairo_set_source_rgb(cr, .1, .1, .1);
3315 if(c->mouse_y > 0 || c->dragging)
3341 cairo_translate(cr, 0,
height);
3343 cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
3357 cairo_set_source_rgba(cr, .7, .7, .7, alpha);
3360 cairo_set_source_rgba(cr, .7, .1, .1, alpha);
3363 cairo_set_source_rgba(cr, .1, .7, .1, alpha);
3366 cairo_set_source_rgba(cr, .1, .1, .7, alpha);
3369 cairo_set_source_rgba(cr, 7, .7, .7, 0.0f);
3378 cairo_set_source_rgba(cr, .7, .7, .7, alpha);
3381 cairo_set_source_rgba(cr, .8, .4, .0, alpha);
3384 cairo_set_source_rgba(cr, .7, .7, .7, 0.0f);
3404 cairo_set_source_rgb(cr, 0.7, 0.7, 0.7);
3415 if(c->mouse_y > 0 || c->dragging)
3418 cairo_set_source_rgba(cr, .7, .7, .7, .6);
3419 cairo_move_to(cr, 0, -
height * c->draw_min_ys[0]);
3424 cairo_close_path(cr);
3427 cairo_set_source_rgba(cr, .9, .9, .9, .5);
3430 const float f =
k - pos;
3432 float ht = -
height * (
f * c->draw_ys[
k] + (1 -
f) * c->draw_ys[
k + 1]);
3433 cairo_arc(cr, c->mouse_x *
width, ht, c->mouse_radius *
width, 0, 2. *
M_PI);
3439 cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
3442 PangoLayout *layout;
3444 PangoFontDescription *desc = pango_font_description_copy_static(
dt_bauhaus_get_global()->pango_font_desc);
3445 pango_font_description_set_weight(desc, PANGO_WEIGHT_BOLD);
3446 pango_font_description_set_absolute_size(desc, (.08 *
height) * PANGO_SCALE);
3447 layout = pango_cairo_create_layout(cr);
3448 pango_layout_set_font_description(layout, desc);
3449 cairo_set_source_rgb(cr, .1, .1, .1);
3451 pango_layout_set_text(layout, _(
"coarse"), -1);
3452 pango_layout_get_pixel_extents(layout, &ink, NULL);
3453 cairo_move_to(cr, .02 *
width - ink.y, .5 * (
height + ink.width));
3455 cairo_rotate(cr, -
M_PI * .5f);
3456 pango_cairo_show_layout(cr, layout);
3459 pango_layout_set_text(layout, _(
"fine"), -1);
3460 pango_layout_get_pixel_extents(layout, &ink, NULL);
3461 cairo_move_to(cr, .98 *
width - ink.height, .5 * (
height + ink.width));
3463 cairo_rotate(cr, -
M_PI * .5f);
3464 pango_cairo_show_layout(cr, layout);
3468 pango_layout_set_text(layout, _(
"smooth"), -1);
3469 pango_layout_get_pixel_extents(layout, &ink, NULL);
3470 cairo_move_to(cr, .5 * (
width - ink.width), .08 *
height - ink.height);
3471 pango_cairo_show_layout(cr, layout);
3473 pango_layout_set_text(layout, _(
"noisy"), -1);
3474 pango_layout_get_pixel_extents(layout, &ink, NULL);
3475 cairo_move_to(cr, .5 * (
width - ink.width), .97 *
height - ink.height);
3476 pango_cairo_show_layout(cr, layout);
3478 pango_font_description_free(desc);
3479 g_object_unref(layout);
3481 cairo_set_source_surface(crf, cst, 0, 0);
3483 cairo_surface_destroy(cst);
3493 GtkAllocation allocation;
3494 gtk_widget_get_allocation(widget, &allocation);
3495 int height = allocation.height - 2 * inset,
width = allocation.width - 2 * inset;
3496 if(!c->dragging) c->mouse_x = CLAMP(event->x - inset, 0,
width) / (float)
width;
3497 c->mouse_y = 1.0 - CLAMP(event->y - inset, 0,
height) / (float)
height;
3500 *
p = c->drag_params;
3511 gtk_widget_queue_draw(widget);
3519 const int ch = c->channel;
3520 if(event->button == 1 && event->type == GDK_2BUTTON_PRESS)
3532 gtk_widget_queue_draw(self->
gui->
widget);
3534 else if(event->button == 1)
3538 GtkAllocation allocation;
3539 gtk_widget_get_allocation(widget, &allocation);
3540 int height = allocation.height - 2 * inset,
width = allocation.width - 2 * inset;
3543 c->mouse_pick -= 1.0 - CLAMP(event->y - inset, 0,
height) / (float)
height;
3552 if(event->button == 1)
3566 if(!c->dragging) c->mouse_y = -1.0;
3567 gtk_widget_queue_draw(widget);
3580 gtk_widget_queue_draw(widget);
3596 gtk_widget_queue_draw(self->
gui->
widget);
3625 g->channel_tabs = GTK_NOTEBOOK(gtk_notebook_new());
3631 gtk_box_pack_start(GTK_BOX(
g->box_wavelets), GTK_WIDGET(
g->channel_tabs),
FALSE,
FALSE, 0);
3633 g->channel_tabs_Y0U0V0 = GTK_NOTEBOOK(gtk_notebook_new());
3637 gtk_box_pack_start(GTK_BOX(
g->box_wavelets), GTK_WIDGET(
g->channel_tabs_Y0U0V0),
FALSE,
FALSE, 0);
3639 const int ch = (int)
g->channel;
3647 g->mouse_x =
g->mouse_y =
g->mouse_pick = -1.0;
3652 g->area = GTK_DRAWING_AREA(gtk_drawing_area_new());
3653 gtk_widget_set_hexpand(GTK_WIDGET(
g->area),
TRUE);
3655 gtk_widget_add_events(GTK_WIDGET(
g->area), GDK_POINTER_MOTION_MASK
3656 | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK
3664 gtk_box_pack_start(GTK_BOX(
g->box_wavelets),
3666 "plugins/darkroom/denoiseprofile/graphheight", 280, 100),
3672 "uniform image if you want to\n"
3673 "estimate the noise variance.")));
3674 gtk_box_pack_start(GTK_BOX(
g->box_variance), GTK_WIDGET(
g->label_var),
TRUE,
TRUE, 0);
3676 GtkBox *hboxR = GTK_BOX(gtk_box_new(GTK_ORIENTATION_HORIZONTAL,
DT_GUI_BOX_SPACING));
3678 gtk_box_pack_start(GTK_BOX(hboxR), GTK_WIDGET(labelR),
FALSE,
FALSE, 0);
3680 gtk_widget_set_tooltip_text(GTK_WIDGET(
g->label_var_R), _(
"variance computed on the red channel"));
3681 gtk_box_pack_start(GTK_BOX(hboxR), GTK_WIDGET(
g->label_var_R),
FALSE,
FALSE, 0);
3682 gtk_box_pack_start(GTK_BOX(
g->box_variance), GTK_WIDGET(hboxR),
TRUE,
TRUE, 0);
3684 GtkBox *hboxG = GTK_BOX(gtk_box_new(GTK_ORIENTATION_HORIZONTAL,
DT_GUI_BOX_SPACING));
3686 gtk_box_pack_start(GTK_BOX(hboxG), GTK_WIDGET(labelG),
FALSE,
FALSE, 0);
3688 gtk_widget_set_tooltip_text(GTK_WIDGET(
g->label_var_G), _(
"variance computed on the green channel"));
3689 gtk_box_pack_start(GTK_BOX(hboxG), GTK_WIDGET(
g->label_var_G),
FALSE,
FALSE, 0);
3690 gtk_box_pack_start(GTK_BOX(
g->box_variance), GTK_WIDGET(hboxG),
TRUE,
TRUE, 0);
3692 GtkBox *hboxB = GTK_BOX(gtk_box_new(GTK_ORIENTATION_HORIZONTAL,
DT_GUI_BOX_SPACING));
3694 gtk_box_pack_start(GTK_BOX(hboxB), GTK_WIDGET(labelB),
FALSE,
FALSE, 0);
3696 gtk_widget_set_tooltip_text(GTK_WIDGET(
g->label_var_B), _(
"variance computed on the blue channel"));
3697 gtk_box_pack_start(GTK_BOX(hboxB), GTK_WIDGET(
g->label_var_B),
FALSE,
FALSE, 0);
3698 gtk_box_pack_start(GTK_BOX(
g->box_variance), GTK_WIDGET(hboxB),
TRUE,
TRUE, 0);
3707 g_signal_connect(G_OBJECT(
g->profile),
"value-changed", G_CALLBACK(
profile_callback), self);
3718 const gboolean compute_variance =
dt_conf_get_bool(
"plugins/darkroom/denoiseprofile/show_compute_variance_mode");
3720 g_signal_connect(G_OBJECT(
g->mode),
"value-changed", G_CALLBACK(
mode_callback), self);
3747 gtk_widget_set_tooltip_text(
g->wb_adaptive_anscombe, _(
"adapt denoising according to the\n"
3748 "white balance coefficients.\n"
3749 "should be enabled on a first instance\n"
3750 "for better denoising.\n"
3751 "should be disabled if an earlier instance\n"
3752 "has been used with a color blending mode."));
3753 gtk_widget_set_tooltip_text(
g->fix_anscombe_and_nlmeans_norm, _(
"fix bugs in anscombe transform resulting\n"
3754 "in undersmoothing of the green channel in\n"
3755 "wavelets mode, combined with a bad handling\n"
3756 "of white balance coefficients, and a bug in\n"
3757 "non local means normalization resulting in\n"
3758 "undersmoothing when patch size was increased.\n"
3759 "enabling this option will change the denoising\n"
3760 "you get. once enabled, you won't be able to\n"
3761 "return back to old algorithm."));
3762 gtk_widget_set_tooltip_text(
g->profile, _(
"profile used for variance stabilization"));
3763 gtk_widget_set_tooltip_text(
g->mode, _(
"method used in the denoising core.\n"
3764 "non-local means works best for `lightness' blending,\n"
3765 "wavelets work best for `color' blending"));
3766 gtk_widget_set_tooltip_text(
g->wavelet_color_mode, _(
"color representation used within the algorithm.\n"
3767 "RGB keeps the RGB channels separated,\n"
3768 "while Y0U0V0 combine the channels to\n"
3769 "denoise chroma and luma separately."));
3770 gtk_widget_set_tooltip_text(
g->radius, _(
"radius of the patches to match.\n"
3771 "increase for more sharpness on strong edges, and better denoising of smooth areas.\n"
3772 "if details are oversmoothed, reduce this value or increase the central pixel weight slider."));
3773 gtk_widget_set_tooltip_text(
g->nbhood, _(
"emergency use only: radius of the neighbourhood to search patches in. "
3774 "increase for better denoising performance, but watch the long runtimes! "
3775 "large radii can be very slow. you have been warned"));
3776 gtk_widget_set_tooltip_text(
g->scattering, _(
"scattering of the neighbourhood to search patches in.\n"
3777 "increase for better coarse-grain noise reduction.\n"
3778 "does not affect execution time."));
3779 gtk_widget_set_tooltip_text(
g->central_pixel_weight, _(
"increase the weight of the central pixel\n"
3780 "of the patch in the patch comparison.\n"
3781 "useful to recover details when patch size\n"
3783 gtk_widget_set_tooltip_text(
g->strength, _(
"finetune denoising strength"));
3784 gtk_widget_set_tooltip_text(
g->overshooting, _(
"controls the way parameters are autoset\n"
3785 "increase if shadows are not denoised enough\n"
3786 "or if chroma noise remains.\n"
3787 "this can happen if your picture is underexposed."));
3788 gtk_widget_set_tooltip_text(
g->shadows, _(
"finetune shadows denoising.\n"
3789 "decrease to denoise more aggressively\n"
3790 "dark areas of the image."));
3791 gtk_widget_set_tooltip_text(
g->bias, _(
"correct color cast in shadows.\n"
3792 "decrease if shadows are too purple.\n"
3793 "increase if shadows are too green."));
3794 gtk_widget_set_tooltip_text(
g->use_new_vst, _(
"upgrade the variance stabilizing algorithm.\n"
3795 "new algorithm extends the current one.\n"
3796 "it is more flexible but could give small\n"
3797 "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)
static const dt_dev_pixelpipe_t * pipe
static const dt_dev_pixelpipe_t const dt_dev_pixelpipe_iop_t * piece
static const dt_iop_drawlayer_params_t * params
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__ int 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)
gboolean dt_opencl_finish(const int devid)
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 gboolean dt_dev_pixelpipe_has_shutdown(const dt_dev_pixelpipe_t *pipe)
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_dev_pixelpipe_type_t type
struct dt_develop_t * dev
struct dt_dev_pixelpipe_t * preview_pipe
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__