80#define MAX_NUM_SCALES 12
87#define DEBUG_DUMP_PFM 0
91static void dump_PFM(
const char *filename,
const float*
out,
const uint32_t w,
const uint32_t h)
93 FILE *
f = g_fopen(filename,
"wb");
94 fprintf(
f,
"PF\n%d %d\n-1.0\n", w, h);
95 for(
int j = h - 1 ; j >= 0 ; j--)
96 for(
int i = 0 ;
i < w ;
i++)
97 for(
int c = 0 ; c < 3 ; c++)
98 fwrite(
out + (j * w +
i) * 4 + c, 1,
sizeof(
float),
f);
191 return _(
"_highlight reconstruction");
198 _(
"linear, raw, scene-referred"),
199 _(
"reconstruction, raw"),
200 _(
"linear, raw, scene-referred"));
231 const float *
const restrict in = (
const float *)input;
232 float max_RGB[3] = { 0.0f };
235 for(
size_t i = 0;
i < roi_out->
height;
i++)
236 for(
size_t j = 0; j < roi_out->
width; j++)
238 const size_t channel =
243 max_RGB[channel] =
MAX(max_RGB[channel], pixel_max);
246 p->clip =
MIN(
MIN(max_RGB[0], max_RGB[1]), max_RGB[2]);
251 void *new_params,
const int new_version)
253 if(old_version == 1 && new_version == 4)
264 n->noise_level = 0.0f;
265 n->reconstructing = 0.4f;
270 n->solid_color = 0.f;
273 if(old_version == 2 && new_version == 4)
288 n->reconstructing = 0.4f;
293 n->solid_color = 0.f;
296 if(old_version == 3 && new_version == 4)
330 const int devid = pipe->
devid;
337 const gboolean visualizing = !
IS_NULL_PTR(
g) &&
g->show_visualize
341 cl_mem dev_xtrans = NULL;
367 if(err != CL_SUCCESS)
goto error;
378 const float clip =
d->clip
393 if(err != CL_SUCCESS)
goto error;
409 if(err != CL_SUCCESS)
goto error;
424 if(err != CL_SUCCESS)
goto error;
429 int blocksizex, blocksizey;
433 .cellsize =
sizeof(float), .overhead = 0,
434 .sizex = 1 << 8, .sizey = 1 << 8 };
438 blocksizex = locopt.
sizex;
439 blocksizey = locopt.
sizey;
442 blocksizex = blocksizey = 1;
449 size_t local[] = { blocksizex, blocksizey, 1 };
459 sizeof(
float) * (blocksizex + 4) * (blocksizey + 4), NULL);
462 if(err != CL_SUCCESS)
goto error;
469 err = (filters == 9u)
472 if(err != CL_SUCCESS)
goto error;
495 const float final_radius = (float)((
int)(1 <<
d->scales)) / scale;
496 const int scales = CLAMP((
int)ceilf(log2f(final_radius)), 1,
MAX_NUM_SCALES);
497 const int max_filter_radius = (1 << scales);
519 tiling->xalign = (filters == 9u) ? 6 : 2;
520 tiling->yalign = (filters == 9u) ? 6 : 2;
554 const ssize_t offset_next,
555 const float clip0,
const float clip_next,
556 const float *
const in,
557 const float *
const ratios)
559 assert(ratio_next != 0);
563 const float clip_val = fmaxf(clip0, clip_next);
564 if(in[offset_next] >= clip_next - 1e-5f)
572 assert(ratio_next != 0);
574 return fminf(in[offset_next] / ratios[ratio_next], clip_val);
576 return fminf(in[offset_next] * ratios[-ratio_next], clip_val);
583 int dim,
int dir,
int other,
584 const float *
const clip,
585 const uint8_t (*
const xtrans)[6],
599 const int roff[3][3] = {{ 0, -1, -2},
608 int i = (dim == 0) ? 0 : other;
609 int j = (dim == 0) ? other : 0;
610 const ssize_t offs = (ssize_t)(dim ? roi_out->
width : 1) * ((dir < 0) ? -1 : 1);
611 const ssize_t offl = offs - (dim ? 1 : roi_out->
width);
612 const ssize_t offr = offs + (dim ? 1 : roi_out->
width);
617 end = (dim == 0) ? roi_out->
width : roi_out->
height;
621 beg = ((dim == 0) ? roi_out->
width : roi_out->
height) - 1;
629 in = (
float *)ivoid + (
size_t)
i + (size_t)beg * roi_in->
width;
633 out = (
float *)
ovoid + (
size_t)beg + (size_t)j * roi_out->
width;
634 in = (
float *)ivoid + (
size_t)beg + (size_t)j * roi_in->
width;
637 for(
int k = beg;
k != end;
k += dir)
644 const uint8_t f0 =
FCxtrans(j,
i, roi_in, xtrans);
645 const uint8_t f1 =
FCxtrans(dim ? (j + dir) : j, dim ?
i : (
i + dir), roi_in, xtrans);
646 const uint8_t fl =
FCxtrans(dim ? (j + dir) : (j - 1), dim ? (
i - 1) : (
i + dir), roi_in, xtrans);
647 const uint8_t fr =
FCxtrans(dim ? (j + dir) : (j + 1), dim ? (
i + 1) : (
i + dir), roi_in, xtrans);
648 const float clip0 = clip[f0];
649 const float clip1 = clip[f1];
650 const float clipl = clip[fl];
651 const float clipr = clip[fr];
652 const float clip_max = fmaxf(fmaxf(clip[0], clip[1]), clip[2]);
654 if(
i == 0 ||
i == roi_out->
width - 1 || j == 0 || j == roi_out->
height - 1)
656 if(pass == 3)
out[0] = fminf(clip_max, in[0]);
663 (in[0] < clip0 && in[0] > 1e-5f) &&
664 (in[offs] < clip1 && in[offs] > 1e-5f))
666 const int r = roff[f0][f1];
669 ratios[
r] = (3.f * ratios[
r] + (in[offs] / in[0])) / 4.f;
671 ratios[-
r] = (3.f * ratios[-
r] + (in[0] / in[offs])) / 4.f;
674 if(in[0] >= clip0 - 1e-5f)
691 out[0] = fminf(clip_max, (
out[0] + add) / 4.0f);
698 if(pass == 3)
out[0] = in[0];
707 const dt_iop_roi_t *
const roi_out,
int dim,
int dir,
int other,
708 const float *clip,
const uint32_t filters,
const int pass)
718 ssize_t offs = dim ? roi_out->
width : 1;
719 if(dir < 0) offs = -offs;
721 if(dim == 0 && dir == 1)
724 end = roi_out->
width;
726 else if(dim == 0 && dir == -1)
728 beg = roi_out->
width - 1;
731 else if(dim == 1 && dir == 1)
736 else if(dim == 1 && dir == -1)
738 beg = roi_out->
height - 1;
747 in = (
float *)ivoid +
i + (
size_t)beg * roi_out->
width;
752 in = (
float *)ivoid + beg + (
size_t)j * roi_out->
width;
754 for(
int k = beg;
k != end;
k += dir)
760 const float clip0 = clip[
FC(j,
i, filters)];
761 const float clip1 = clip[
FC(dim ? (j + 1) : j, dim ?
i : (
i + 1), filters)];
762 if(
i == 0 ||
i == roi_out->
width - 1 || j == 0 || j == roi_out->
height - 1)
764 if(pass == 3)
out[0] = in[0];
768 if(in[0] < clip0 && in[0] > 1e-5f)
770 if(in[offs] < clip1 && in[offs] > 1e-5f)
773 ratio = (3.0f * ratio + in[0] / in[offs]) / 4.0f;
775 ratio = (3.0f * ratio + in[offs] / in[0]) / 4.0f;
779 if(in[0] >= clip0 - 1e-5f)
782 if(in[offs] >= clip1 - 1e-5f)
783 add = fmaxf(clip0, clip1);
785 add = in[offs] * ratio;
787 add = in[offs] / ratio;
792 out[0] = (
out[0] + add) / 4.0f;
798 if(pass == 3)
out[0] = in[0];
815#define SQRT3 1.7320508075688772935274463415058723669L
816#define SQRT12 3.4641016151377545870548926830117447339L
825 for(
int j = 0; j < roi_out->
height; j++)
827 for(
int i = 0;
i < roi_out->
width;
i++)
829 float *
const out = (
float *)
ovoid + (
size_t)roi_out->
width * j +
i;
830 const float *
const in = (
float *)ivoid + (
size_t)roi_out->
width * j +
i;
835 out[0] =
MIN(clip, in[0]);
842 float R = 0.0f, Gmin = FLT_MAX, Gmax = -FLT_MAX,
B = 0.0f;
843 for(
int jj = 0; jj <= 1; jj++)
845 for(
int ii = 0; ii <= 1; ii++)
847 const float val = in[(size_t)jj * roi_out->
width + ii];
849 clipped = (clipped || (val > clip));
851 const int c =
FC(j + jj + roi_out->
y,
i + ii + roi_out->
x, filters);
858 Gmin =
MIN(Gmin, val);
859 Gmax =
MAX(Gmax, val);
870 const float Ro =
MIN(
R, clip);
871 const float Go =
MIN(Gmin, clip);
872 const float Bo =
MIN(
B, clip);
874 const float L = (
R + Gmax +
B) / 3.0f;
877 float H = 2.0f *
B - Gmax -
R;
879 const float Co =
SQRT3 * (Ro - Go);
880 const float Ho = 2.0f * Bo - Go - Ro;
882 if(
R != Gmax && Gmax !=
B)
884 const float ratio = sqrtf((Co * Co + Ho * Ho) / (
C *
C +
H *
H));
902 RGB[2] =
L +
H / 3.0f;
904 out[0] =
RGB[
FC(j + roi_out->
y,
i + roi_out->
x, filters)];
921 const uint8_t(*
const xtrans)[6] = (
const uint8_t(*
const)[6])piece->
dsc_in.
xtrans;
923 for(
int j = 0; j < roi_out->
height; j++)
926 float *in = (
float *)ivoid + (
size_t)roi_in->
width * j;
933 for(
int i = 0;
i < roi_out->
width;
i++)
937 if(j >= 2 && j <= roi_out->
height - 3)
939 cl |= (in[-roi_in->
width] > clip) | (in[0] > clip) | (in[roi_in->
width] > clip);
942 if(i < 2 || i > roi_out->
width - 3 || j < 2 || j > roi_out->
height - 3)
945 out[0] =
MIN(clip, in[0]);
950 int clipped = (in[0] > clip);
964 for(
int offset_j = -2; offset_j <= 0; offset_j++)
966 for(
int offset_i = -2; offset_i <= 0; offset_i++)
971 for(
int jj = offset_j; jj <= offset_j + 2; jj++)
973 for(
int ii = offset_i; ii <= offset_i + 2; ii++)
975 const float val = in[(ssize_t)jj * roi_in->
width + ii];
976 clipped = (clipped || (val > clip));
989 int cnt[3] = { 0, 0, 0 };
991 for(
int jj = -1; jj <= 1; jj++)
993 for(
int ii = -1; ii <= 1; ii++)
995 const float val = in[(ssize_t)jj * roi_in->
width + ii];
996 const int c =
FCxtrans(j+jj,
i+ii, roi_in, xtrans);
999 RGBmax[c] =
MAX(RGBmax[c], val);
1003 const float Ro =
MIN(mean[0]/cnt[0], clip);
1004 const float Go =
MIN(mean[1]/cnt[1], clip);
1005 const float Bo =
MIN(mean[2]/cnt[2], clip);
1007 const float R = RGBmax[0];
1008 const float G = RGBmax[1];
1009 const float B = RGBmax[2];
1011 const float L = (
R + G +
B) / 3.0f;
1014 float H = 2.0f *
B - G -
R;
1016 const float Co =
SQRT3 * (Ro - Go);
1017 const float Ho = 2.0f * Bo - Go - Ro;
1019 if(
R != G && G !=
B)
1021 const float ratio = sqrtf((Co * Co + Ho * Ho) / (
C *
C +
H *
H));
1030 RGB[2] =
L +
H / 3.0f;
1049 float *
const restrict interpolated,
1050 float *
const restrict clipping_mask,
1053 const uint32_t filters,
1059 for(
size_t j = 0; j <
width; j++)
1061 const size_t c =
FC(
i, j, filters);
1062 const size_t i_center =
i *
width;
1063 const float center = input[i_center + j];
1082 R_clipped = G_clipped = B_clipped = (center > clips[c]);
1086 const size_t i_prev = (
i - 1) *
width;
1087 const size_t i_next = (
i + 1) *
width;
1088 const size_t j_prev = (j - 1);
1089 const size_t j_next = (j + 1);
1091 const float north = input[i_prev + j];
1092 const float south = input[i_next + j];
1093 const float west = input[i_center + j_prev];
1094 const float east = input[i_center + j_next];
1096 const float north_east = input[i_prev + j_next];
1097 const float north_west = input[i_prev + j_prev];
1098 const float south_east = input[i_next + j_next];
1099 const float south_west = input[i_next + j_prev];
1104 G_clipped = (center > clips[
GREEN]);
1109 G = (north + south + east + west) / 4.f;
1110 G_clipped = (north > clips[
GREEN] || south > clips[
GREEN] || east > clips[
GREEN] || west > clips[
GREEN]);
1116 R_clipped = (center > clips[
RED]);
1120 if(
FC(
i - 1, j, filters) ==
RED &&
FC(
i + 1, j, filters) ==
RED)
1123 R = (north + south) / 2.f;
1124 R_clipped = (north > clips[
RED] || south > clips[
RED]);
1126 else if(
FC(
i, j - 1, filters) ==
RED &&
FC(
i, j + 1, filters) ==
RED)
1129 R = (west + east) / 2.f;
1130 R_clipped = (west > clips[
RED] || east > clips[
RED]);
1135 R = (north_west + north_east + south_east + south_west) / 4.f;
1136 R_clipped = (north_west > clips[
RED] || north_east > clips[
RED] || south_west > clips[
RED]
1137 || south_east > clips[
RED]);
1144 B_clipped = (center > clips[
BLUE]);
1148 if(
FC(
i - 1, j, filters) ==
BLUE &&
FC(
i + 1, j, filters) ==
BLUE)
1151 B = (north + south) / 2.f;
1152 B_clipped = (north > clips[
BLUE] || south > clips[
BLUE]);
1154 else if(
FC(
i, j - 1, filters) ==
BLUE &&
FC(
i, j + 1, filters) ==
BLUE)
1157 B = (west + east) / 2.f;
1158 B_clipped = (west > clips[
BLUE] || east > clips[
BLUE]);
1163 B = (north_west + north_east + south_east + south_west) / 4.f;
1165 B_clipped = (north_west > clips[
BLUE] || north_east > clips[
BLUE] || south_west > clips[
BLUE]
1166 || south_east > clips[
BLUE]);
1172 dt_aligned_pixel_t clipped = { R_clipped, G_clipped, B_clipped, (R_clipped || G_clipped || B_clipped) };
1176 const size_t idx = (
i *
width + j) * 4 +
k;
1177 interpolated[idx] = fmaxf(
RGB[
k] / wb[
k], 0.f);
1178 clipping_mask[idx] = clipped[
k];
1194 const uint32_t filters,
1195 const uint8_t (*
const xtrans)[6],
1201 const float n_pixels = roi_in->
height * roi_in->
width;
1203 for(
size_t i = 0;
i < roi_in->
height;
i++)
1204 for(
size_t j = 0; j < roi_in->
width; j++)
1206 const int c = (filters == 9u) ?
FCxtrans((
int)
i, (int)j, roi_in, xtrans) :
FC(
i, j, filters);
1207 if(c < 0 || c > 2)
continue;
1209 const float value = input[
i * roi_in->
width + j] / n_pixels;
1218 normalization[
RED] = sum_R;
1219 normalization[
GREEN] = sum_G;
1220 normalization[
BLUE] = sum_B;
1221 normalization[
ALPHA] = 1.f;
1233 const uint8_t (*
const xtrans)[6])
1237 for(
int col = 0; col < 6; col++)
1245 for(
int y = -1; y <= 1; y++)
1246 for(
int x = -1;
x <= 1;
x++)
1248 const int weight = 1 << ((y == 0) + (
x == 0));
1249 const int color =
FCxtrans(
row + y, col +
x, roi_in, xtrans);
1250 if(color ==
f)
continue;
1251 *ip++ = (y << 16) | (
x & 0xffffu);
1258 for(
int c = 0; c < 3; c++)
1277 float *
const restrict interpolated,
1278 float *
const restrict clipping_mask,
1282 const int32_t
lookup[6][6][32],
1283 const uint8_t (*
const xtrans)[6],
1288 for(
size_t j = 0; j <
width; j++)
1290 const size_t idx =
i *
width + j;
1291 const float center = input[idx];
1299 int count[3] = { 0 };
1300 int used_clipped[3] = { 0 };
1301 const int f =
FCxtrans((
int)
i, (
int)j, roi_in, xtrans);
1305 for(
int y =
MAX((
int)
i - 1, 0); y <=
MIN((
int)
i + 1, (
int)
height - 1); y++)
1306 for(
int x =
MAX((
int)j - 1, 0);
x <=
MIN((
int)j + 1, (
int)
width - 1);
x++)
1308 const int color =
FCxtrans(y,
x, roi_in, xtrans);
1310 sum[color] +=
value;
1312 used_clipped[color] |= (
value > clips[color]);
1315 for(
int c = 0; c < 3; c++)
1317 const int has_samples = (count[c] > 0);
1318 RGB[c] = (c ==
f || !has_samples) ? center : sum[c] / count[c];
1319 clipped[c] = (c ==
f || !has_samples) ? (center > clips[c]) : used_clipped[c];
1324 const int32_t *ip = &(
lookup[
i % 6][j % 6][0]);
1326 int used_clipped[3] = { 0 };
1327 const int neighbours = *ip++;
1331 for(
int k = 0;
k < neighbours;
k++, ip += 3)
1333 const int32_t offset = ip[0];
1334 const int x = (int16_t)(offset & 0xffffu);
1335 const int y = (int16_t)(offset >> 16);
1336 const size_t neighbour = ((size_t)((
int)
i + y) *
width + (
size_t)((int)j +
x));
1337 const int color = ip[2];
1338 const float value = input[neighbour];
1339 sum[color] +=
value * ip[1];
1340 used_clipped[color] |= (
value > clips[color]);
1345 for(
int k = 0;
k < 2;
k++, ip += 2)
1347 const int color = ip[0];
1348 const int total = ip[1];
1349 RGB[color] = (total > 0) ? sum[color] / total : center;
1350 clipped[color] = used_clipped[color];
1355 clipped[
f] = (center > clips[
f]);
1363 const size_t index = idx * 4 +
k;
1364 interpolated[index] = fmaxf(
RGB[
k] / wb[
k], 0.f);
1365 clipping_mask[index] = clipped[
k];
1373 const float *
const restrict interpolated,
1374 const float *
const restrict clipping_mask,
1375 float *
const restrict output,
1377 const uint32_t filters,
1383 for(
size_t j = 0; j <
width; j++)
1385 const size_t c =
FC(
i, j, filters);
1386 const size_t idx =
i *
width + j;
1387 const size_t index = idx * 4;
1388 const float opacity = clipping_mask[index +
ALPHA];
1389 output[idx] = opacity * fmaxf(interpolated[index + c] * wb[c], 0.f)
1390 + (1.f - opacity) * input[idx];
1398 const float *
const restrict interpolated,
1399 const float *
const restrict clipping_mask,
1400 float *
const restrict output,
1403 const uint8_t (*
const xtrans)[6],
1408 for(
size_t j = 0; j <
width; j++)
1410 const size_t idx =
i *
width + j;
1411 const size_t index = idx * 4;
1412 const int c =
FCxtrans((
int)
i, (
int)j, roi_in, xtrans);
1413 const float opacity = clipping_mask[index +
ALPHA];
1414 output[idx] = opacity * fmaxf(interpolated[index + c] * wb[c], 0.f)
1415 + (1.f - opacity) * input[idx];
1435static inline __attribute__((always_inline)) uint8_t scale_type(
const int s,
const int scales)
1445static inline void guide_laplacians(
const float *
const restrict high_freq,
const float *
const restrict low_freq,
1446 const float *
const restrict clipping_mask,
1447 float *
const restrict output,
const size_t width,
const size_t height,
1448 const int mult,
const float noise_level,
const int salt,
1449 const uint8_t scale,
const float radius_sq)
1454 const dt_aligned_pixel_simd_t zero =
dt_simd_set1(0.f);
1455 const dt_aligned_pixel_simd_t ones =
dt_simd_set1(1.f);
1456 const dt_aligned_pixel_simd_t inv_patch =
dt_simd_set1(1.f / 9.f);
1457 const dt_aligned_pixel_simd_t scale_multiplier =
dt_simd_set1(1.f / radius_sq);
1458 const float eps = 1e-12f;
1464 const float *
const row0 = HF + 4 * ((size_t)
MAX(
i - mult, 0) *
width);
1465 const float *
const row1 = HF + 4 * ((size_t)
i *
width);
1468 const int max_col = (int)
width - 1;
1470 for(
int j = 0; j <
width; ++j)
1472 const size_t idx = (
i *
width + j);
1473 const size_t index = idx * 4;
1474 const float alpha = clipping_mask[index +
ALPHA];
1475 const float alpha_comp = 1.f - alpha;
1476 dt_aligned_pixel_simd_t high_frequency = dt_load_simd_aligned(HF + index);
1480 const int col_offsets[3]
1481 = { 4 *
MAX(j - mult, 0),
1483 4 *
MIN(j + mult, max_col) };
1484 dt_aligned_pixel_simd_t sum = zero;
1485 dt_aligned_pixel_simd_t sum_sq = zero;
1486 dt_aligned_pixel_simd_t prod_r = zero;
1487 dt_aligned_pixel_simd_t prod_g = zero;
1488 dt_aligned_pixel_simd_t prod_b = zero;
1493#if defined(__GNUC__) && !defined(__clang__)
1496 for(
int jj = 0; jj < 3; ++jj)
1498 const float *
const row_ptr = rows[jj];
1499#if defined(__GNUC__) && !defined(__clang__)
1502 for(
int ii = 0; ii < 3; ++ii)
1504 const dt_aligned_pixel_simd_t sample = dt_load_simd_aligned(row_ptr + col_offsets[ii]);
1507 sum_sq += sample * sample;
1514 dt_aligned_pixel_simd_t means = sum * inv_patch;
1515 dt_aligned_pixel_simd_t variance = sum_sq * inv_patch - means * means;
1516 variance = dt_simd_max_zero(variance);
1517 variance[
ALPHA] = 0.f;
1519 size_t guiding_channel =
RED;
1520 float guide_variance = variance[
RED];
1521 if(variance[
GREEN] > guide_variance)
1523 guiding_channel =
GREEN;
1524 guide_variance = variance[
GREEN];
1526 if(variance[
BLUE] > guide_variance)
1528 guiding_channel =
BLUE;
1529 guide_variance = variance[
BLUE];
1532 if(guide_variance >
eps)
1534 const float guide_mean = means[guiding_channel];
1535 dt_aligned_pixel_simd_t covariance
1536 = (guiding_channel ==
RED ? prod_r : (guiding_channel ==
GREEN ? prod_g : prod_b)) * inv_patch
1538 dt_aligned_pixel_simd_t slope = covariance /
dt_simd_set1(guide_variance);
1539 slope = dt_simd_max_zero(slope);
1540 dt_aligned_pixel_simd_t intercept = means - slope *
dt_simd_set1(guide_mean);
1541 const dt_aligned_pixel_simd_t blend = dt_load_simd_aligned(clipping_mask + index) * scale_multiplier;
1542 const dt_aligned_pixel_simd_t guide =
dt_simd_set1(high_frequency[guiding_channel]);
1543 high_frequency = blend * (slope * guide + intercept) + (ones - blend) * high_frequency;
1547 dt_aligned_pixel_simd_t out_pixel = high_frequency;
1555 out_pixel += dt_load_simd_aligned(
out + index);
1561 out_pixel = dt_simd_max_zero(out_pixel + dt_load_simd_aligned(LF + index));
1565 if((scale &
LAST_SCALE) && salt && alpha > 0.f)
1589 noise[c] = current[c] + fabsf(
noise[c] - current[c]);
1591 out_pixel[
RED] = fmaxf(alpha *
noise[
RED] + alpha_comp * current[
RED], 0.f);
1600 const float norm = fmaxf(sqrtf(sqf(out_pixel[
RED]) + sqf(out_pixel[
GREEN]) + sqf(out_pixel[
BLUE])), 1e-6f);
1602 out_pixel[
ALPHA] = norm;
1612static inline void heat_PDE_diffusion(
const float *
const restrict high_freq,
const float *
const restrict low_freq,
1613 const float *
const restrict clipping_mask,
1614 float *
const restrict output,
const size_t width,
const size_t height,
1615 const int mult,
const uint8_t scale,
1616 const float first_order_factor)
1636 const size_t i_neighbours[3]
1637 = {
MAX((
int)(
i - mult), (
int)0) *
width,
1642 = { 0.25f, 0.5f, 0.25f, 0.5f, -3.f, 0.5f, 0.25f, 0.5f, 0.25f };
1644 for(
size_t j = 0; j <
width; ++j)
1646 const size_t idx = (
i *
width + j);
1647 const size_t index = idx * 4;
1651 clipping_mask[index +
GREEN],
1652 clipping_mask[index +
BLUE],
1653 clipping_mask[index +
ALPHA] };
1655 dt_aligned_pixel_t high_frequency = { HF[index + 0], HF[index + 1], HF[index + 2], HF[index + 3] };
1661 const float norm_backup = high_frequency[3];
1663 if(alpha[
ALPHA] > 0.f)
1666 const size_t j_neighbours[3]
1667 = {
MAX((
int)(j - mult), (
int)0),
1669 MIN((
int)(j + mult), (
int)
width - 1) };
1675 neighbour_pixel_HF[3 * 0 + 0][c] = HF[4 * (i_neighbours[0] + j_neighbours[0]) + c];
1676 neighbour_pixel_HF[3 * 0 + 1][c] = HF[4 * (i_neighbours[0] + j_neighbours[1]) + c];
1677 neighbour_pixel_HF[3 * 0 + 2][c] = HF[4 * (i_neighbours[0] + j_neighbours[2]) + c];
1679 neighbour_pixel_HF[3 * 1 + 0][c] = HF[4 * (i_neighbours[1] + j_neighbours[0]) + c];
1680 neighbour_pixel_HF[3 * 1 + 1][c] = HF[4 * (i_neighbours[1] + j_neighbours[1]) + c];
1681 neighbour_pixel_HF[3 * 1 + 2][c] = HF[4 * (i_neighbours[1] + j_neighbours[2]) + c];
1683 neighbour_pixel_HF[3 * 2 + 0][c] = HF[4 * (i_neighbours[2] + j_neighbours[0]) + c];
1684 neighbour_pixel_HF[3 * 2 + 1][c] = HF[4 * (i_neighbours[2] + j_neighbours[1]) + c];
1685 neighbour_pixel_HF[3 * 2 + 2][c] = HF[4 * (i_neighbours[2] + j_neighbours[2]) + c];
1691 for(
int k = 0;
k < 9;
k++)
1693 for_each_channel(c, aligned(laplacian_HF, neighbour_pixel_HF:16) aligned(anisotropic_kernel_isophote: 64))
1694 laplacian_HF[c] += neighbour_pixel_HF[
k][c] * anisotropic_kernel_isophote[
k];
1699 for_each_channel(c, aligned(high_frequency, multipliers_HF, laplacian_HF, alpha))
1700 high_frequency[c] += alpha[c] * multipliers_HF[c] * (laplacian_HF[c] - first_order_factor * high_frequency[c]);
1703 high_frequency[3] = norm_backup;
1710 out[index + c] = high_frequency[c];
1716 out[index + c] += high_frequency[c];
1723 out[index + c] = fmaxf(
out[index + c] + LF[index + c], 0.f);
1726 if(alpha[
ALPHA] > 0.f)
1730 out[index + c] /= (c !=
ALPHA && norm > 1e-4f) ? norm : 1.f;
1744 *
const restrict reconstructed,
1745 const float *
const restrict clipping_mask,
1748 float *
const restrict HF,
1749 float *
const restrict LF_odd,
1750 float *
const restrict LF_even,
1752 const float noise_level,
1753 const int salt,
const float first_order_factor)
1764 for(
int s = 0; s < scales; ++s)
1767 const int mult = 1 << s;
1769 const float *restrict buffer_in;
1770 float *restrict buffer_out;
1775 buffer_out = LF_odd;
1780 buffer_out = LF_even;
1784 buffer_in = LF_even;
1785 buffer_out = LF_odd;
1790 uint8_t current_scale_type = scale_type(s, scales);
1794 guide_laplacians(HF, buffer_out, clipping_mask, reconstructed,
width,
height, mult, noise_level, salt, current_scale_type, radius);
1800 sprintf(
name,
"/tmp/scale-input-%i.pfm", s);
1803 sprintf(
name,
"/tmp/scale-blur-%i.pfm", s);
1816 void *
const restrict
ovoid,
1831 const size_t ds_size = ds_height * ds_width;
1842 const float final_radius = (float)((
int)(1 << data->
scales)) / scale;
1843 const int scales = CLAMP((
int)ceilf(log2f(final_radius)), 1,
MAX_NUM_SCALES);
1845 const float noise_level = data->
noise_level / scale;
1858 const float *
const restrict input = (
const float *
const restrict)ivoid;
1859 float *
const restrict output = (
float *
const restrict)
ovoid;
1877 if(
wavelets_process(ds_interpolated, temp, ds_clipping_mask, ds_width, ds_height, scales, HF, LF_odd,
1883 if(
wavelets_process(temp, ds_interpolated, ds_clipping_mask, ds_width, ds_height, scales, HF, LF_odd,
1896 dump_PFM(
"/tmp/interpolated.pfm", interpolated,
width,
height);
1897 dump_PFM(
"/tmp/clipping_mask.pfm", clipping_mask,
width,
height);
1915 void *
const restrict
ovoid,
1923 const uint8_t(*
const xtrans)[6] = (
const uint8_t(*
const)[6])piece->
dsc_in.
xtrans;
1931 const size_t ds_size = ds_height * ds_width;
1940 const float final_radius = (float)((
int)(1 << data->
scales)) / scale;
1941 const int scales = CLAMP((
int)ceilf(log2f(final_radius)), 1,
MAX_NUM_SCALES);
1942 const float noise_level = data->
noise_level / scale;
1954 const float *
const restrict input = (
const float *
const restrict)ivoid;
1955 float *
const restrict output = (
float *
const restrict)
ovoid;
1957 int32_t
lookup[6][6][32] = { { { 0 } } };
1974 if(
wavelets_process(ds_interpolated, temp, ds_clipping_mask, ds_width, ds_height, scales, HF, LF_odd,
1980 if(
wavelets_process(temp, ds_interpolated, ds_clipping_mask, ds_width, ds_height, scales, HF, LF_odd,
2005 cl_mem in, cl_mem reconstructed,
2006 cl_mem reconstructed_scratch,
2007 cl_mem clipping_mask,
2008 const size_t sizes[3],
const int width,
const int height,
2015 const float noise_level,
2016 const int salt,
const float solid_color)
2019 cl_mem reconstruct_read = reconstructed_scratch;
2024 for(
int s = 0; s < scales; ++s)
2027 const int mult = 1 << s;
2035 buffer_out = LF_odd;
2040 buffer_out = LF_even;
2044 buffer_in = LF_even;
2045 buffer_out = LF_odd;
2049 const int clamp_lf = 1;
2052 .yoffset = 0, .yfactor = 1,
2053 .cellsize = 4 *
sizeof(float), .overhead = 0,
2054 .sizex = 1 << 16, .sizey = 1 };
2056 hblocksize = hlocopt.
sizex;
2063 const size_t horizontal_local[3] = { hblocksize, 1, 1 };
2071 (hblocksize + 4 * mult) * 4 *
sizeof(
float), NULL);
2073 horizontal_sizes, horizontal_local);
2085 if(err != CL_SUCCESS)
return err;
2089 .yoffset = 2 * mult, .yfactor = 1,
2090 .cellsize = 4 *
sizeof(float), .overhead = 0,
2091 .sizex = 1, .sizey = 1 << 16 };
2093 vblocksize = vlocopt.
sizey;
2100 const size_t vertical_local[3] = { 1, vblocksize, 1 };
2108 (vblocksize + 4 * mult) * 4 *
sizeof(
float), NULL);
2110 vertical_sizes, vertical_local);
2122 if(err != CL_SUCCESS)
return err;
2124 uint8_t current_scale_type = scale_type(s, scales);
2126 cl_mem reconstruct_write = (s == scales - 1)
2128 : (reconstruct_read == reconstructed ? reconstructed_scratch : reconstructed);
2147 if(err != CL_SUCCESS)
return err;
2162 if(err != CL_SUCCESS)
return err;
2165 reconstruct_read = reconstruct_write;
2181 const int devid = pipe->
devid;
2195 cl_mem normalization = NULL;
2196 cl_mem normalization_tmp = NULL;
2197 cl_mem normalization_partials = NULL;
2198 cl_mem normalization_final = NULL;
2206 const float final_radius = (float)((
int)(1 << data->
scales)) / scale;
2207 const int scales = CLAMP((
int)ceilf(log2f(final_radius)), 1,
MAX_NUM_SCALES);
2209 const float noise_level = data->
noise_level / scale;
2215 cl_mem reconstructed_scratch =
dt_opencl_alloc_device(devid, ds_sizes[0], ds_sizes[1],
sizeof(
float) * 4);
2226 .cellsize = 4 *
sizeof(float), .overhead = 0,
2227 .sizex = 1 << 4, .sizey = 1 << 4 };
2234 const int bufsize = (int)((bwidth / flocopt.
sizex) * (bheight / flocopt.
sizey));
2239 if(!normalization_partials || !normalization || !normalization_tmp)
goto error;
2241 size_t fsizes[3] = { bwidth, bheight, 1 };
2242 size_t flocal[3] = { flocopt.
sizex, flocopt.
sizey, 1 };
2251 sizeof(
float) * 4 * flocopt.
sizex * flocopt.
sizey, NULL);
2253 if(err != CL_SUCCESS)
goto error;
2257 .cellsize = 4 *
sizeof(float), .overhead = 0,
2258 .sizex = 1 << 16, .sizey = 1 };
2263 int current_length = bufsize;
2264 cl_mem reduce_in = normalization_partials;
2265 cl_mem reduce_out = normalization;
2270 size_t ssizes[3] = { (size_t)reducesize * slocopt.
sizex, 1, 1 };
2271 size_t slocal[3] = { slocopt.
sizex, 1, 1 };
2276 sizeof(
float) * 4 * slocopt.
sizex, NULL);
2278 if(err != CL_SUCCESS)
goto error;
2280 if(reducesize == 1)
break;
2281 current_length = reducesize;
2282 cl_mem
swap = reduce_in;
2283 reduce_in = reduce_out;
2284 reduce_out = (
swap == normalization_partials) ? normalization_tmp : normalization;
2287 normalization_final = reduce_out;
2298 (
void *)&roi_out->
height);
2300 if(err != CL_SUCCESS)
goto error;
2307 if(err != CL_SUCCESS)
goto error;
2310 const int RGBa =
TRUE;
2319 if(err != CL_SUCCESS)
goto error;
2329 if(err != CL_SUCCESS)
goto error;
2334 err =
wavelets_process_cl(devid, ds_interpolated, temp, reconstructed_scratch, ds_clipping_mask,
2335 ds_sizes, ds_width, ds_height, gd, scales, HF, LF_odd, LF_even,
2337 if(err != CL_SUCCESS)
goto error;
2339 err =
wavelets_process_cl(devid, temp, ds_interpolated, reconstructed_scratch, ds_clipping_mask,
2340 ds_sizes, ds_width, ds_height, gd, scales, HF, LF_odd, LF_even,
2342 if(err != CL_SUCCESS)
goto error;
2353 if(err != CL_SUCCESS)
goto error;
2365 if(err != CL_SUCCESS)
goto error;
2414 const uint8_t(*
const xtrans)[6] = (
const uint8_t(*
const)[6])piece->
dsc_in.
xtrans;
2415 const int devid = pipe->
devid;
2427 cl_mem normalization = NULL;
2428 cl_mem normalization_tmp = NULL;
2429 cl_mem normalization_partials = NULL;
2430 cl_mem normalization_final = NULL;
2436 const float final_radius = (float)((
int)(1 << data->
scales)) / scale;
2437 const int scales = CLAMP((
int)ceilf(log2f(final_radius)), 1,
MAX_NUM_SCALES);
2438 const float noise_level = data->
noise_level / scale;
2443 cl_mem reconstructed_scratch =
dt_opencl_alloc_device(devid, ds_sizes[0], ds_sizes[1],
sizeof(
float) * 4);
2447 int32_t
lookup[6][6][32] = { { { 0 } } };
2460 .cellsize = 4 *
sizeof(float), .overhead = 0,
2461 .sizex = 1 << 4, .sizey = 1 << 4 };
2468 const int bufsize = (int)((bwidth / flocopt.
sizex) * (bheight / flocopt.
sizey));
2473 if(!normalization_partials || !normalization || !normalization_tmp)
goto error;
2475 size_t fsizes[3] = { bwidth, bheight, 1 };
2476 size_t flocal[3] = { flocopt.
sizex, flocopt.
sizey, 1 };
2485 sizeof(
float) * 4 * flocopt.
sizex * flocopt.
sizey, NULL);
2487 if(err != CL_SUCCESS)
goto error;
2491 .cellsize = 4 *
sizeof(float), .overhead = 0,
2492 .sizex = 1 << 16, .sizey = 1 };
2497 int current_length = bufsize;
2498 cl_mem reduce_in = normalization_partials;
2499 cl_mem reduce_out = normalization;
2504 size_t ssizes[3] = { (size_t)reducesize * slocopt.
sizex, 1, 1 };
2505 size_t slocal[3] = { slocopt.
sizex, 1, 1 };
2510 sizeof(
float) * 4 * slocopt.
sizex, NULL);
2512 if(err != CL_SUCCESS)
goto error;
2514 if(reducesize == 1)
break;
2515 current_length = reducesize;
2516 cl_mem
swap = reduce_in;
2517 reduce_in = reduce_out;
2518 reduce_out = (
swap == normalization_partials) ? normalization_tmp : normalization;
2521 normalization_final = reduce_out;
2536 if(err != CL_SUCCESS)
goto error;
2543 if(err != CL_SUCCESS)
goto error;
2545 const int RGBa =
TRUE;
2554 if(err != CL_SUCCESS)
goto error;
2564 if(err != CL_SUCCESS)
goto error;
2569 err =
wavelets_process_cl(devid, ds_interpolated, temp, reconstructed_scratch, ds_clipping_mask,
2570 ds_sizes, ds_width, ds_height, gd, scales, HF, LF_odd, LF_even,
2572 if(err != CL_SUCCESS)
goto error;
2574 err =
wavelets_process_cl(devid, temp, ds_interpolated, reconstructed_scratch, ds_clipping_mask,
2575 ds_sizes, ds_width, ds_height, gd, scales, HF, LF_odd, LF_even,
2577 if(err != CL_SUCCESS)
goto error;
2587 if(err != CL_SUCCESS)
goto error;
2600 if(err != CL_SUCCESS)
goto error;
2647 const float *
const in = (
const float *
const)ivoid;
2648 float *
const out = (
float *
const)
ovoid;
2653 for(
size_t k = 0;
k < (size_t)roi_out->
width * roi_out->
height;
k++)
2676 const float *
const in = (
const float *
const)ivoid;
2677 float *
const out = (
float *
const)
ovoid;
2689 const int c =
FC(
row, col, filters);
2690 const float ival = in[
i];
2691 out[
i] = (ival < clips[c]) ? 0.2f * ival : 1.0f;
2709 const gboolean visualizing = !
IS_NULL_PTR(
g) &&
g->show_visualize
2743 const uint8_t(*
const xtrans)[6] = (
const uint8_t(*
const)[6])piece->
dsc_in.
xtrans;
2745 for(
int j = 0; j < roi_out->
height; j++)
2752 for(
int i = 0;
i < roi_out->
width;
i++)
2762 for(
int j = 0; j < roi_out->
height; j++)
2771 for(
int i = 0;
i < roi_out->
width;
i++)
2812 memcpy(
d,
p,
sizeof(*
p));
2819 dt_iop_fmt_log(self,
"commit: class=%s filters=%u mode=%d -> enabled=%d",
2859 const gboolean
state = current_state && active;
2860 dt_iop_fmt_log(self,
"force_enable: class=%s supported=%d current=%d -> %d",
2862 active, current_state,
state);
2868 const int program = 2;
2889 const int wavelets = 35;
2965 gtk_stack_set_visible_child_name(GTK_STACK(self->
widget), self->
default_enabled ?
"default" :
"monochrome");
2968 g->show_visualize =
FALSE;
2979 module->default_enabled = enable(&module->dev->image_storage);
2980 module->hide_enable_button = !enable(&module->dev->image_storage);
2981 dt_iop_fmt_log(module,
"reload_defaults: class=%s default_enabled=%d",
2985 gtk_stack_set_visible_child_name(GTK_STACK(module->
widget), module->
default_enabled ?
"default" :
"monochrome");
3007 if(
g->show_visualize)
3019 const gboolean was_visualize =
g->show_visualize;
3021 g->show_visualize =
FALSE;
3032 gtk_widget_set_tooltip_text(
g->mode, _(
"highlight reconstruction method"));
3036 gtk_widget_set_tooltip_text(
g->clip,
3037 _(
"manually adjust the clipping threshold against "
3038 "magenta highlights\nthe mask icon shows the clipped area\n"
3039 "(you shouldn't ever need to touch this)"));
3046 gtk_widget_set_tooltip_text(
g->noise_level, _(
"add noise to visually blend the reconstructed areas\n"
3047 "into the rest of the noisy image. useful at high ISO."));
3051 gtk_widget_set_tooltip_text(
g->iterations, _(
"increase if magenta highlights don't get fully corrected\n"
3052 "each new iteration brings a performance penalty."));
3056 gtk_widget_set_tooltip_text(
g->solid_color, _(
"increase if magenta highlights don't get fully corrected.\n"
3057 "this may produce non-smooth boundaries between valid and clipped regions."));
3060 gtk_widget_set_tooltip_text(
g->scales, _(
"increase to correct larger clipped areas.\n"
3061 "large values bring huge performance penalties"));
3064 gtk_widget_set_tooltip_text(monochromes, _(
"no highlights reconstruction for monochrome images"));
3067 self->
widget = gtk_stack_new();
3068 gtk_stack_set_homogeneous(GTK_STACK(self->
widget),
FALSE);
3069 gtk_stack_add_named(GTK_STACK(self->
widget), monochromes,
"monochrome");
3070 gtk_stack_add_named(GTK_STACK(self->
widget), box_raw,
"default");
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_widget_set_quad_toggle(GtkWidget *widget, int toggle)
int dt_bauhaus_combobox_length(GtkWidget *widget)
void dt_bauhaus_widget_set_quad_active(GtkWidget *widget, int active)
void dt_bauhaus_combobox_add_full(GtkWidget *widget, const char *text, dt_bauhaus_combobox_alignment_t align, gpointer data, void(free_func)(void *data), gboolean sensitive)
int dt_bauhaus_widget_get_quad_active(GtkWidget *widget)
void dt_bauhaus_widget_set_quad_visibility(GtkWidget *widget, const gboolean visible)
void dt_bauhaus_slider_set_format(GtkWidget *widget, const char *format)
void dt_bauhaus_widget_set_quad_paint(GtkWidget *widget, dt_bauhaus_quad_paint_f f, int paint_flags, void *paint_data)
@ DT_BAUHAUS_COMBOBOX_ALIGN_RIGHT
int dt_box_mean(float *const buf, const size_t height, const size_t width, const int ch, const int radius, const unsigned iterations)
static float equivalent_sigma_at_step(const float sigma, const unsigned int s)
#define B_SPLINE_TO_LAPLACIAN
static void decompose_2D_Bspline(const float *const restrict in, float *const restrict HF, float *const restrict LF, const size_t width, const size_t height, const int mult, float *const tempbuf, size_t padded_size)
static const dt_aligned_pixel_simd_t const dt_adaptation_t const float p
return vector dt_simd_set1(valid ?(scaling+NORM_MIN) :NORM_MIN)
static float lookup(read_only image2d_t lut, const float x)
const dt_aligned_pixel_t f
const dt_colormatrix_t dt_aligned_pixel_t out
dt_store_simd_aligned(out, dt_mat3x4_mul_vec4(vin, dt_colormatrix_row_to_simd(matrix, 0), dt_colormatrix_row_to_simd(matrix, 1), dt_colormatrix_row_to_simd(matrix, 2)))
static const float const float C
static dt_aligned_pixel_t RGB
typedef void((*dt_cache_allocate_t)(void *userdata, dt_cache_entry_t *entry))
dt_image_pipe_class_t dt_image_pipe_class(const dt_image_t *img)
const char * dt_image_pipe_class_name(const dt_image_pipe_class_t klass)
gboolean dt_image_is_monochrome(const dt_image_t *img)
gboolean dt_image_needs_rawprepare(const dt_image_t *img)
void dt_print(dt_debug_thread_t thread, const char *msg,...)
static const dt_aligned_pixel_simd_t const dt_aligned_pixel_simd_t row1
#define dt_free_align(ptr)
static void * dt_calloc_align(size_t size)
#define for_each_channel(_var,...)
float dt_aligned_pixel_simd_t __attribute__((vector_size(16), aligned(16)))
Enable aggressive floating-point arithmetic optimizations, in denormals handling. Set through user pr...
#define DT_MODULE_INTROSPECTION(MODVER, PARAMSTYPE)
#define dt_pixelpipe_cache_free_align(mem)
#define dt_pixelpipe_cache_alloc_align_float(pixels, pipe)
#define __DT_CLONE_TARGETS__
static const dt_aligned_pixel_simd_t const dt_aligned_pixel_simd_t const dt_aligned_pixel_simd_t row2
#define for_four_channels(_var,...)
#define __OMP_PARALLEL_FOR__(...)
static const dt_aligned_pixel_simd_t value
#define __OMP_FOR_SIMD__(...)
#define __OMP_PARALLEL_FOR_SIMD__(...)
#define dt_pixelpipe_cache_alloc_perthread_float(n, padded_size)
static const dt_aligned_pixel_simd_t row0
#define IS_NULL_PTR(p)
C is way too permissive with !=, == and if(var) checks, which can mean too many things depending on w...
static int FCxtrans(const int row, const int col, global const unsigned char(*const xtrans)[6])
static int FC(const int row, const int col, const unsigned int filters)
static float4 dt_noise_generator_simd(const dt_noise_distribution_t distribution, const float4 mu, const float4 param, uint state[4])
static unsigned int splitmix32(const unsigned long seed)
static float xoshiro128plus(uint state[4])
#define dt_dev_pixelpipe_update_history_main(dev)
@ DT_DEV_PIXELPIPE_DISPLAY_MASK
@ DT_DEV_PIXELPIPE_DISPLAY_PASSTHRU
@ DT_DEV_PIXELPIPE_DISPLAY_NONE
void dtgtk_cairo_paint_showmask(cairo_t *cr, gint x, gint y, gint w, gint h, gint flags, void *data)
static int dwt_interleave_rows(const int rowid, const int height, const int stride)
static void weight(const float *c1, const float *c2, const float sharpen, dt_aligned_pixel_t weight)
static __DT_CLONE_TARGETS__ void interpolate_bilinear(const float *const restrict in, const size_t width_in, const size_t height_in, float *const restrict out, const size_t width_out, const size_t height_out, const size_t ch)
#define DT_GUI_BOX_SPACING
static GtkWidget * dt_ui_label_new(const gchar *str)
static __DT_CLONE_TARGETS__ void _compute_laplacian_normalization(const float *const restrict input, const dt_iop_roi_t *const roi_in, const uint32_t filters, const uint8_t(*const xtrans)[6], dt_aligned_pixel_t normalization)
static cl_int process_laplacian_bayer_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, const dt_aligned_pixel_t clips)
void commit_params(struct dt_iop_module_t *self, dt_iop_params_t *p1, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
static __DT_CLONE_TARGETS__ int process_laplacian_bayer(struct dt_iop_module_t *self, const dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece, const void *const restrict ivoid, void *const restrict ovoid, const dt_iop_roi_t *const roi_in, const dt_iop_roi_t *const roi_out, const dt_aligned_pixel_t clips)
const char ** description(struct dt_iop_module_t *self)
__DT_CLONE_TARGETS__ 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 heat_PDE_diffusion(const float *const restrict high_freq, const float *const restrict low_freq, const float *const restrict clipping_mask, float *const restrict output, const size_t width, const size_t height, const int mult, const uint8_t scale, const float first_order_factor)
void reload_defaults(dt_iop_module_t *module)
static int wavelets_process(const float *const restrict in, float *const restrict reconstructed, const float *const restrict clipping_mask, const size_t width, const size_t height, const int scales, float *const restrict HF, float *const restrict LF_odd, float *const restrict LF_even, const diffuse_reconstruct_variant_t variant, const float noise_level, const int salt, const float first_order_factor)
@ DT_IOP_HIGHLIGHTS_INPAINT
@ DT_IOP_HIGHLIGHTS_LAPLACIAN
static __DT_CLONE_TARGETS__ void _remosaic_and_replace_xtrans(const float *const restrict input, const float *const restrict interpolated, const float *const restrict clipping_mask, float *const restrict output, const dt_aligned_pixel_t wb, const dt_iop_roi_t *const roi_in, const uint8_t(*const xtrans)[6], const size_t width, const size_t height)
dt_atrous_wavelets_scales_t
static __DT_CLONE_TARGETS__ void _build_xtrans_bilinear_lookup(int32_t lookup[6][6][32], const dt_iop_roi_t *const roi_in, const uint8_t(*const xtrans)[6])
static gboolean enable(dt_image_t *image)
static __DT_CLONE_TARGETS__ void process_lch_xtrans(dt_iop_module_t *self, 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 float clip)
void gui_focus(struct dt_iop_module_t *self, gboolean in)
void init_pipe(struct dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
static __DT_CLONE_TARGETS__ int process_laplacian_xtrans(struct dt_iop_module_t *self, const dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece, const void *const restrict ivoid, void *const restrict ovoid, const dt_iop_roi_t *const roi_in, const dt_iop_roi_t *const roi_out, const dt_aligned_pixel_t clips)
static void interpolate_color(const void *const ivoid, void *const ovoid, const dt_iop_roi_t *const roi_out, int dim, int dir, int other, const float *clip, const uint32_t filters, const int pass)
void output_format(dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece, dt_iop_buffer_dsc_t *dsc)
static __DT_CLONE_TARGETS__ void _interpolate_and_mask(const float *const restrict input, float *const restrict interpolated, float *const restrict clipping_mask, const dt_aligned_pixel_t clips, const dt_aligned_pixel_t wb, const uint32_t filters, const size_t width, const size_t height)
static __DT_CLONE_TARGETS__ void _remosaic_and_replace(const float *const restrict input, const float *const restrict interpolated, const float *const restrict clipping_mask, float *const restrict output, const dt_aligned_pixel_t wb, const uint32_t filters, const size_t width, const size_t height)
void gui_update(struct dt_iop_module_t *self)
Refresh GUI controls from current params and configuration.
void gui_init(struct dt_iop_module_t *self)
void gui_changed(dt_iop_module_t *self, GtkWidget *w, void *previous)
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)
diffuse_reconstruct_variant_t
@ DIFFUSE_RECONSTRUCT_RGB
@ DIFFUSE_RECONSTRUCT_CHROMA
void cleanup_global(dt_iop_module_so_t *module)
static cl_int process_laplacian_xtrans_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, const dt_aligned_pixel_t clips)
dt_iop_highlights_params_t dt_iop_highlights_data_t
static __DT_CLONE_TARGETS__ void process_lch_bayer(dt_iop_module_t *self, 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 float clip)
int default_colorspace(dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece)
void autoset(struct dt_iop_module_t *self, const struct dt_dev_pixelpipe_t *pipe, const struct dt_dev_pixelpipe_iop_t *piece, const void *input)
static __DT_CLONE_TARGETS__ void process_clip(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 float clip)
gboolean force_enable(struct dt_iop_module_t *self, const gboolean current_state)
static __DT_CLONE_TARGETS__ void guide_laplacians(const float *const restrict high_freq, const float *const restrict low_freq, const float *const restrict clipping_mask, float *const restrict output, const size_t width, const size_t height, const int mult, const float noise_level, const int salt, const uint8_t scale, const float radius_sq)
static float interp_pix_xtrans(const int ratio_next, const ssize_t offset_next, const float clip0, const float clip_next, const float *const in, const float *const ratios)
void cleanup_pipe(struct dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
static void _visualize_callback(GtkWidget *quad, gpointer user_data)
static __DT_CLONE_TARGETS__ void process_visualize(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 uint32_t filters, dt_iop_highlights_data_t *data)
void init_global(dt_iop_module_so_t *module)
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 cl_int wavelets_process_cl(const int devid, cl_mem in, cl_mem reconstructed, cl_mem reconstructed_scratch, cl_mem clipping_mask, const size_t sizes[3], const int width, const int height, dt_iop_highlights_global_data_t *const gd, const int scales, cl_mem HF, cl_mem LF_odd, cl_mem LF_even, const diffuse_reconstruct_variant_t variant, const float noise_level, const int salt, const float solid_color)
static __DT_CLONE_TARGETS__ void _interpolate_and_mask_xtrans(const float *const restrict input, float *const restrict interpolated, float *const restrict clipping_mask, const dt_aligned_pixel_t clips, const dt_aligned_pixel_t wb, const dt_iop_roi_t *const roi_in, const int32_t lookup[6][6][32], const uint8_t(*const xtrans)[6], const size_t width, const size_t height)
static void interpolate_color_xtrans(const void *const ivoid, void *const ovoid, const dt_iop_roi_t *const roi_in, const dt_iop_roi_t *const roi_out, int dim, int dir, int other, const float *const clip, const uint8_t(*const xtrans)[6], const int pass)
int legacy_params(dt_iop_module_t *self, const void *const old_params, const int old_version, void *new_params, const int new_version)
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)
float dt_dev_get_module_scale(const dt_dev_pixelpipe_t *const pipe, const dt_iop_roi_t *const roi_in)
void dt_iop_set_cache_bypass(dt_iop_module_t *module, gboolean state)
#define dt_iop_fmt_log(module, fmt,...)
Debug helper to trace a module's input-format-driven decisions on the -d pipe channel (DT_DEBUG_PIPE)...
@ IOP_FLAGS_SUPPORTS_BLENDING
#define IOP_GUI_ALLOC(module)
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 void swap(float *x, float *y)
float *const restrict const size_t k
float *const restrict const size_t const size_t ch
float dt_aligned_pixel_t[4]
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)
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 DT_OPENCL_DEFAULT_ERROR
struct _GtkWidget GtkWidget
const float uint32_t state[4]
const float const int flip
struct dt_gui_gtk_t * gui
dt_iop_buffer_dsc_t dsc_out
dt_iop_buffer_dsc_t dsc_in
struct dt_iop_module_t *void * data
gboolean cache_output_on_ram
struct dt_dev_pixelpipe_t * pipe
dt_aligned_pixel_t processed_maximum
int kernel_highlights_diffuse_color
int kernel_highlights_1f_clip
int kernel_highlights_guide_laplacians
int kernel_highlights_1f_lch_xtrans
int kernel_highlights_1f_lch_bayer
int kernel_highlights_remosaic_and_replace
int kernel_filmic_bspline_horizontal_local
int kernel_highlights_normalize_reduce_first
int kernel_highlights_4f_clip
int kernel_highlights_bilinear_and_mask_xtrans
int kernel_highlights_normalize_reduce_first_xtrans
int kernel_interpolate_bilinear
int kernel_filmic_bspline_horizontal
int kernel_highlights_box_blur
int kernel_filmic_bspline_vertical
int kernel_highlights_normalize_reduce_second
int kernel_highlights_remosaic_and_replace_xtrans
int kernel_highlights_false_color
int kernel_highlights_bilinear_and_mask
int kernel_filmic_bspline_vertical_local
dt_iop_highlights_mode_t mode
dt_atrous_wavelets_scales_t scales
dt_iop_global_data_t * data
int32_t hide_enable_button
struct dt_develop_t * dev
dt_iop_gui_data_t * gui_data
dt_iop_global_data_t * global_data
Region of interest passed through the pixelpipe.