95 #define INLINE __inline
100#define DEMOSAIC_XTRANS 1024
101#define DEMOSAIC_DUAL 2048
104#define XTRANS_SNAPPER 3
105#define BAYER_SNAPPER 2
106#define DOWNSAMPLE_GUIDED_SCALES 1
245 return a * (b - c) + c;
281 const float *
const in,
285 const uint32_t filters);
302 return _(
"demosaic");
307 return dt_iop_set_description(self, _(
"reconstruct full RGB pixels from a sensor color filter array reading"),
309 _(
"linear, raw, scene-referred"),
311 _(
"linear, RGB, scene-referred"));
330 void *new_params,
const int new_version)
333 typedef struct dt_iop_demosaic_params_v3_t
340 } dt_iop_demosaic_params_v3_t;
342 if(old_version == 3 && new_version == 4)
344 dt_iop_demosaic_params_v3_t *o = (dt_iop_demosaic_params_v3_t *)old_params;
345 dt_iop_demosaic_params_v4_t *
n = (dt_iop_demosaic_params_v4_t *)new_params;
346 memcpy(
n, o,
sizeof *o);
347 n->dual_thrs = 0.20f;
351 if(old_version == 2 && new_version == 3)
357 n->color_smoothing = 0;
397 string =
"passthrough monochrome";
400 string =
"photosites";
409 string =
"RCD + VNG4";
412 string =
"AMaZE + VNG4";
415 string =
"VNG (xtrans)";
418 string =
"Markesteijn-1 (XTrans)";
421 string =
"Markesteijn-3 (XTrans)";
424 string =
"Markesteijn 3-pass + VNG";
427 string =
"Frequency Domain Chroma (XTrans)";
430 string =
"passthrough monochrome (XTrans)";
433 string =
"photosites (XTrans)";
436 string =
"downsample";
439 string =
"(unknown method)";
460 const dt_iop_roi_t *
const roi_in,
const uint32_t filters,
461 const gboolean is_4bayer,
const double CAM_to_RGB[3][4])
464 for(
int y = 0; y < roi_out->
height; y++)
466 for(
int x = 0;
x < roi_out->
width;
x++)
468 float *
const outc =
out + 4 * ((size_t)y * roi_out->
width +
x);
470 int samples[4] = { 0 };
471 const int px =
MIN(2 *
x, roi_in->
width - 1);
472 const int py =
MIN(2 * y, roi_in->
height - 1);
476 for(
int j = 0; j < 2; j++)
478 for(
int i = 0;
i < 2;
i++)
480 const int xx =
MIN(px +
i, roi_in->
width - 1);
481 const int yy =
MIN(py + j, roi_in->
height - 1);
482 const int c =
FC(yy, xx, filters);
483 cam[c] += in[(size_t)yy * roi_in->
width + xx];
488 for(
int c = 0; c < 4; c++)
489 if(samples[c] > 0) cam[c] /= (float)samples[c];
493 for(
int c = 0; c < 3; c++)
496 for(
int k = 0;
k < 4;
k++) outc[c] += CAM_to_RGB[c][
k] * cam[
k];
502 outc[1] = cam[
GREEN];
521 const int px,
const int py,
522 const uint8_t (*
const xtrans)[6],
const int colour)
524 const float cx = px + 0.5f;
525 const float cy = py + 0.5f;
526 const int xmin =
MAX(0, px - 3);
527 const int xmax =
MIN(roi_in->
width - 1, px + 4);
528 const int ymin =
MAX(0, py - 3);
529 const int ymax =
MIN(roi_in->
height - 1, py + 4);
531 float quadrant_value[4] = { 0.0f };
532 float quadrant_dist[4] = { INFINITY, INFINITY, INFINITY, INFINITY };
533 int quadrant_x[4] = { 0 };
534 int quadrant_y[4] = { 0 };
537 float nearest_value = 0.0f;
538 float nearest_dist = INFINITY;
542 for(
int yy = ymin; yy <= ymax; yy++)
544 for(
int xx = xmin; xx <= xmax; xx++)
546 if(
FCxtrans(yy, xx, roi_in, xtrans) != colour)
continue;
548 const float dx = xx - cx;
549 const float dy = yy - cy;
550 const float dist2 = dx * dx + dy * dy;
551 if(dist2 < nearest_dist)
553 nearest_dist = dist2;
554 nearest_value = in[(size_t)yy * roi_in->
width + xx];
557 const int quadrant = ((yy > cy) ? 2 : 0) + ((xx > cx) ? 1 : 0);
558 if(dist2 < quadrant_dist[quadrant])
560 quadrant_dist[quadrant] = dist2;
561 quadrant_value[quadrant] = in[(size_t)yy * roi_in->
width + xx];
562 quadrant_x[quadrant] = xx;
563 quadrant_y[quadrant] = yy;
564 quadrant_valid[quadrant] =
TRUE;
569 if(quadrant_valid[0] && quadrant_valid[1] && quadrant_valid[2] && quadrant_valid[3])
571 const float x_left = 0.5f * (quadrant_x[0] + quadrant_x[2]);
572 const float x_right = 0.5f * (quadrant_x[1] + quadrant_x[3]);
573 const float y_top = 0.5f * (quadrant_y[0] + quadrant_y[1]);
574 const float y_bottom = 0.5f * (quadrant_y[2] + quadrant_y[3]);
575 const float tx = CLAMP((cx - x_left) /
MAX(x_right - x_left, 1e-6f), 0.0f, 1.0f);
576 const float ty = CLAMP((cy - y_top) /
MAX(y_bottom - y_top, 1e-6f), 0.0f, 1.0f);
577 const float top = quadrant_value[0] + tx * (quadrant_value[1] - quadrant_value[0]);
578 const float bottom = quadrant_value[2] + tx * (quadrant_value[3] - quadrant_value[2]);
579 return top + ty * (bottom -
top);
584 for(
int q = 0; q < 4; q++)
586 if(!quadrant_valid[q])
continue;
587 sum += quadrant_value[q];
591 return (count > 0) ? sum / (float)count : nearest_value;
605 const uint8_t (*
const xtrans)[6])
608 for(
int y = 0; y < roi_out->
height; y++)
610 for(
int x = 0;
x < roi_out->
width;
x++)
612 float *
const outc =
out + 4 * ((size_t)y * roi_out->
width +
x);
614 int samples[3] = { 0 };
615 const int px =
MIN(2 *
x, roi_in->
width - 1);
616 const int py =
MIN(2 * y, roi_in->
height - 1);
620 for(
int j = 0; j < 2; j++)
622 for(
int i = 0;
i < 2;
i++)
624 const int xx =
MIN(px +
i, roi_in->
width - 1);
625 const int yy =
MIN(py + j, roi_in->
height - 1);
626 const int c =
FCxtrans(yy, xx, roi_in, xtrans);
627 rgb[c] += in[(size_t)yy * roi_in->
width + xx];
632 for(
int c = 0; c < 3; c++)
635 outc[c] =
rgb[c] / (float)samples[c];
659 float *
const restrict
coeff,
660 float *
const restrict bias,
663 const float eps = 1e-12f;
665 const dt_aligned_pixel_simd_t inv_patch =
dt_simd_set1(1.f / 25.f);
669 const float *
const row0 = HF + 4 * ((size_t)CLAMP((
int)
row - 2, 0, (int)
height - 1) *
width);
670 const float *
const row1 = HF + 4 * ((size_t)CLAMP((
int)
row - 1, 0, (int)
height - 1) *
width);
672 const float *
const row3 = HF + 4 * ((size_t)CLAMP((
int)
row + 1, 0, (int)
height - 1) *
width);
673 const float *
const row4 = HF + 4 * ((size_t)CLAMP((
int)
row + 2, 0, (int)
height - 1) *
width);
675 const int max_col = (int)
width - 1;
677 for(
size_t col = 0; col <
width; ++col)
679 dt_aligned_pixel_simd_t sum_rgb = zero;
680 dt_aligned_pixel_simd_t sum_rgb_guide = zero;
681 float sum_guide = 0.f;
682 float sum_guide_sq = 0.f;
684 = { 4 * CLAMP((
int)col - 2, 0, max_col),
685 4 * CLAMP((
int)col - 1, 0, max_col),
687 4 * CLAMP((
int)col + 1, 0, max_col),
688 4 * CLAMP((
int)col + 2, 0, max_col) };
695#if defined(__GNUC__) && !defined(__clang__)
700 const float *
const row_ptr = rows[jj];
701#if defined(__GNUC__) && !defined(__clang__)
706 const dt_aligned_pixel_simd_t sample = dt_load_simd_aligned(row_ptr + col_offsets[ii]);
707 const float guide = (sample[
RED] + sample[
GREEN] + sample[
BLUE]) / 3.f;
711 sum_guide_sq += guide * guide;
716 dt_aligned_pixel_simd_t means = sum_rgb * inv_patch;
717 const float guide_mean = sum_guide * (1.f / 25.f);
718 float variance = sum_guide_sq * (1.f / 25.f) - sqf(guide_mean);
719 dt_aligned_pixel_simd_t covariance = sum_rgb_guide * inv_patch - means *
dt_simd_set1(guide_mean);
721 covariance[
ALPHA] = 0.f;
723 if(variance < 0.f) variance = 0.f;
725 dt_aligned_pixel_simd_t slope = zero;
729 dt_aligned_pixel_simd_t intercept = means - slope *
dt_simd_set1(guide_mean);
730 intercept[
ALPHA] = 0.f;
748 const float *
const restrict
coeff,
749 const float *
const restrict bias,
750 const float *
const restrict LF,
751 float *
const restrict reconstructed,
753 const gboolean
reset)
758 for(
size_t col = 0; col <
width; ++col)
760 const size_t index = 4 * (
row *
width + col);
761 const dt_aligned_pixel_simd_t hf = dt_load_simd_aligned(HF + index);
763 dt_aligned_pixel_simd_t filtered = (dt_load_simd_aligned(
coeff + index) * guide
764 + dt_load_simd_aligned(bias + index))
765 * dt_load_simd_aligned(LF + index);
767 if(!
reset) filtered += dt_load_simd_aligned(reconstructed + index);
768 filtered[
ALPHA] = 0.f;
789 const int iterations)
791 if(iterations <= 0)
return 0;
803 const float *restrict residual =
out;
812 for(
int iteration = 0; iteration < iterations; ++iteration)
818 const int mult = 1 << s;
819 const float *restrict buffer_in;
820 float *restrict buffer_out;
830 buffer_out = LF_even;
844 for(
size_t col = 0; col <
width; ++col)
846 const size_t index = 4 * (
row *
width + col);
847 dt_aligned_pixel_simd_t lf = dt_load_simd_aligned(buffer_out + index);
848 lf[
RED] = fmaxf(lf[
RED], 1e-8f);
853 dt_aligned_pixel_simd_t normalized = dt_load_simd_aligned(HF + index) / lf;
854 normalized[
ALPHA] = 0.f;
868 residual = buffer_out;
871 const gboolean last_iteration = (iteration == iterations - 1);
875 for(
size_t col = 0; col <
width; ++col)
877 const size_t index = 4 * (
row *
width + col);
878 dt_aligned_pixel_simd_t pixel
879 = dt_simd_max_zero(dt_load_simd_aligned(reconstructed + index)
880 + dt_load_simd_aligned(residual + index));
884 dt_store_simd_nontemporal(
out + index, pixel);
906 const float *
const in,
float *
const out,
const dt_iop_roi_t *
const roi_in,
970 const int dx = roi_in->
x % aligner;
971 const int dy = roi_in->
y % aligner;
972 const int shift_x = (dx > aligner / 2) ? aligner - dx : -dx;
973 const int shift_y = (dy > aligner / 2) ? aligner - dy : -dy;
975 roi_in->
x =
MAX(0, roi_in->
x + shift_x);
976 roi_in->
y =
MAX(0, roi_in->
y + shift_y);
983 const void *
const i,
void *
const o)
989 dt_times_t start_time = { 0 }, end_time = { 0 };
998 const uint8_t(*
const xtrans)[6] = (
const uint8_t(*
const)[6])piece->
dsc_in.
xtrans;
1005 gboolean showmask =
FALSE;
1009 if(
g) showmask = (
g->visual_mask);
1017 const float *
const pixels = (
float *)
i;
1055 float *in = (
float *)pixels;
1067 roi_in->
x, roi_in->
y);
1081 roi_in->
x, roi_in->
y);
1129 for(
int j = 0; j < 65536; j++)
1131 const double x = (
double)j / 65535.0;
1132 gd->
lmmse_gamma_in[j] = (
x <= 0.001867) ?
x * 17.0 : 1.044445 * exp(log(
x) / 2.4) - 0.044445;
1133 gd->
lmmse_gamma_out[j] = (
x <= 0.031746) ?
x / 17.0 : exp(log((
x + 0.044445) / 1.044445) * 2.4);
1156 const float mpixels = (roo.
width * roo.
height) / 1.0e6;
1158 const float tclock = end_time.clock - start_time.
clock;
1159 const float uclock = end_time.user - start_time.
user;
1160 fprintf(stderr,
" [demosaic] process CPU `%s' did %.2fmpix, %.4f secs (%.4f CPU), %.2f pix/us\n",
1161 method2string(demosaicing_method & ~
DEMOSAIC_DUAL), mpixels, tclock, uclock, mpixels / tclock);
1180 const dt_iop_roi_t *
const roi_out,
const int demosaicing_method)
1185 const int devid = pipe->
devid;
1187 cl_mem dev_aux = NULL;
1188 cl_mem dev_tmp = NULL;
1189 cl_mem dev_med = NULL;
1190 cl_mem dev_green_eq = NULL;
1205 dev_in = dev_green_eq;
1219 if(err != CL_SUCCESS)
goto error;
1233 if(err != CL_SUCCESS)
goto error;
1241 const int myborder = 3;
1251 if(err != CL_SUCCESS)
goto error;
1261 .cellsize = 1 *
sizeof(float), .overhead = 0,
1262 .sizex = 1 << 8, .sizey = 1 << 8 };
1268 size_t local[3] = { locopt.
sizex, locopt.
sizey, 1 };
1277 sizeof(
float) * (locopt.
sizex + 4) * (locopt.
sizey + 4), NULL);
1279 if(err != CL_SUCCESS)
goto error;
1288 .cellsize =
sizeof(float) * 1, .overhead = 0,
1289 .sizex = 1 << 8, .sizey = 1 << 8 };
1295 size_t local[3] = { locopt.
sizex, locopt.
sizey, 1 };
1303 sizeof(
float) * (locopt.
sizex + 2*3) * (locopt.
sizey + 2*3), NULL);
1306 if(err != CL_SUCCESS)
goto error;
1312 .cellsize = 4 *
sizeof(float), .overhead = 0,
1313 .sizex = 1 << 8, .sizey = 1 << 8 };
1319 size_t local[3] = { locopt.
sizex, locopt.
sizey, 1 };
1327 sizeof(
float) * 4 * (locopt.
sizex + 2) * (locopt.
sizey + 2), NULL);
1330 if(err != CL_SUCCESS)
goto error;
1338 dev_aux = dev_green_eq = dev_tmp = dev_med = NULL;
1362 const int iterations)
1364 if(iterations <= 0)
return TRUE;
1367 const int devid = pipe->
devid;
1370 const int clip_negatives = 1;
1371 const int keep_signed = 0;
1372 const int dense_mult = 1;
1375 cl_mem LF_even = NULL;
1376 cl_mem LF_odd = NULL;
1378 cl_mem
coeff = NULL;
1380 cl_mem coeff_tmp = NULL;
1381 cl_mem reconstructed_a = NULL;
1382 cl_mem reconstructed_b = NULL;
1383 cl_mem residual = NULL;
1384 cl_mem reconstructed_read = NULL;
1385 cl_mem reconstructed_write = NULL;
1386 cl_mem reconstructed_final = NULL;
1401 for(
int iteration = 0; iteration < iterations; ++iteration)
1403 reconstructed_read = reconstructed_a;
1404 reconstructed_write = reconstructed_b;
1405 reconstructed_final = NULL;
1410 const int mult = 1 << s;
1411 const int first_scale = (s == 0);
1417 buffer_in = dev_out;
1418 buffer_out = LF_odd;
1423 buffer_out = LF_even;
1427 buffer_in = LF_even;
1428 buffer_out = LF_odd;
1433 .yoffset = 0, .yfactor = 1,
1434 .cellsize = 4 *
sizeof(float), .overhead = 0,
1435 .sizex = 1 << 16, .sizey = 1 };
1437 hblocksize = hlocopt.
sizex;
1444 const size_t horizontal_local[3] = { hblocksize, 1, 1 };
1452 (hblocksize + 4 * mult) * 4 *
sizeof(
float), NULL);
1454 horizontal_sizes, horizontal_local);
1466 if(err != CL_SUCCESS)
goto error;
1470 .yoffset = 2 * mult, .yfactor = 1,
1471 .cellsize = 4 *
sizeof(float), .overhead = 0,
1472 .sizex = 1, .sizey = 1 << 16 };
1474 vblocksize = vlocopt.
sizey;
1481 const size_t vertical_local[3] = { 1, vblocksize, 1 };
1489 (vblocksize + 4 * mult) * 4 *
sizeof(
float), NULL);
1491 vertical_sizes, vertical_local);
1503 if(err != CL_SUCCESS)
goto error;
1511 if(err != CL_SUCCESS)
goto error;
1519 if(err != CL_SUCCESS)
goto error;
1528 if(err != CL_SUCCESS)
goto error;
1537 if(err != CL_SUCCESS)
goto error;
1546 if(err != CL_SUCCESS)
goto error;
1555 if(err != CL_SUCCESS)
goto error;
1567 if(err != CL_SUCCESS)
goto error;
1569 residual = buffer_out;
1570 reconstructed_final = reconstructed_write;
1571 cl_mem tmp = reconstructed_read;
1572 reconstructed_read = reconstructed_write;
1573 reconstructed_write = tmp;
1582 if(err != CL_SUCCESS)
goto error;
1609 cl_mem dev_in, cl_mem dev_out)
1613 dt_times_t start_time = { 0 }, end_time = { 0 };
1622 gboolean showmask =
FALSE;
1626 if(
g) showmask = (
g->visual_mask);
1634 cl_mem high_image = NULL;
1635 cl_mem low_image = NULL;
1636 cl_mem blend = NULL;
1637 cl_mem details = NULL;
1638 cl_mem dev_aux = NULL;
1639 cl_mem dev_xtrans = NULL;
1641 const int devid = pipe->
devid;
1642 gboolean retval =
FALSE;
1650 if(!
process_default_cl(self, pipe, piece, dev_in, dev_out, roi_in, roi_out, demosaicing_method))
return FALSE;
1674 if(err != CL_SUCCESS)
goto finish;
1702 if(err != CL_SUCCESS)
goto finish;
1716 if(!
process_rcd_cl(self, pipe, piece, dev_in, high_image, roi_in, roi_in,
FALSE))
goto finish;
1743 dt_print(
DT_DEBUG_OPENCL,
"[opencl_demosaic] demosaicing method '%s' not yet supported by opencl code\n", method2string(demosaicing_method));
1749 const float mpixels = (roi_in->
width * roi_in->
height) / 1.0e6;
1751 const float tclock = end_time.clock - start_time.
clock;
1752 const float uclock = end_time.user - start_time.
user;
1753 fprintf(stderr,
" [demosaic] process GPU `%s' did %.2fmpix, %.4f secs (%.4f CPU), %.2f pix/us\n",
1754 method2string(demosaicing_method & ~
DEMOSAIC_DUAL), mpixels, tclock, uclock, mpixels / tclock);
1792 retval =
dual_demosaic_cl(self, pipe, piece, details, blend, high_image, low_image, dev_aux,
width,
height, showmask);
1798 fprintf(stderr,
" [demosaic] GPU dual blending %.4f secs (%.4f CPU)\n", end_time.clock - start_time.
clock, end_time.user - start_time.
user);
1805 if(err != CL_SUCCESS)
1816 if(!retval && dual)
dt_control_log(_(
"[dual demosaic_cl] internal problem"));
1848 tiling->factor = 1.0f + ioratio;
1849 tiling->factor += fmax(1.0f + greeneq, smooth);
1864 tiling->factor = 1.0f + ioratio;
1865 tiling->factor += ndir * 1.0f
1870 tiling->factor += fmax(1.0f + greeneq, smooth);
1875 tiling->overlap = overlap;
1879 tiling->factor = 1.0f + ioratio;
1880 tiling->factor += fmax(1.0f + greeneq, smooth);
1890 tiling->factor = 1.0f + ioratio;
1891 tiling->factor += fmax(1.0f + greeneq, smooth);
1901 tiling->factor = 1.0f + ioratio;
1902 tiling->factor += fmax(1.0f + greeneq, smooth);
1923 const int program = 0;
1939 const int other = 14;
1952 const int markesteijn = 16;
1986 const int wavelets = 35;
2073 dt_iop_fmt_log(self,
"force_enable: class=%s needs_demosaic=%d current=%d -> %d",
2086 d->green_eq =
p->green_eq;
2087 d->color_smoothing =
p->color_smoothing;
2088 d->median_thrs =
p->median_thrs;
2089 d->dual_thrs =
p->dual_thrs;
2090 d->lmmse_refine =
p->lmmse_refine;
2111 d->median_thrs = 0.0f;
2116 d->color_smoothing = 0;
2117 d->dual_thrs = 0.0f;
2122 d->dual_thrs = 0.0f;
2126 d->color_smoothing = 0;
2128 d->demosaicing_method = use_method;
2131 switch(
d->demosaicing_method)
2197 NULL,
d->CAM_to_RGB,
2201 fprintf(stderr,
"[colorspaces] `%s' color matrix not found for 4bayer image!\n", camera);
2202 dt_control_log(_(
"`%s' color matrix not found for 4bayer image!"), camera);
2206 dt_iop_fmt_log(self,
"commit: class=%s in(filters=%u ch=%i) method=%d passthrough=%d -> enabled=%d cl_ready=%d",
2235 module->hide_enable_button = 1;
2239 module->default_enabled = dt_image_needs_demosaic(&module->dev->image_storage);
2240 dt_iop_fmt_log(module,
"reload_defaults: class=%s needs_demosaic=%d filters=%u mono=%d method=%d -> default_enabled=%d",
2247 gtk_stack_set_visible_child_name(GTK_STACK(module->
widget), module->
default_enabled ?
"raw" :
"non_raw");
2267 const gboolean isdual = !isdownsample && (use_method &
DEMOSAIC_DUAL);
2274 gtk_widget_set_visible(
g->demosaic_method_bayer, bayer);
2275 gtk_widget_set_visible(
g->demosaic_method_xtrans, !bayer);
2281 gtk_widget_set_visible(
g->median_thrs, bayer && isppg);
2282 gtk_widget_set_visible(
g->greeneq, !passing && !isdownsample);
2283 gtk_widget_set_visible(
g->color_smoothing, !passing && !isdual);
2284 gtk_widget_set_visible(
g->dual_thrs, isdual);
2285 gtk_widget_set_visible(
g->lmmse_refine, islmmse);
2292 img->
flags &= ~DT_IMAGE_MONOCHROME_BAYER;
2303 gtk_stack_set_visible_child_name(GTK_STACK(self->
widget), self->
default_enabled ?
"raw" :
"non_raw");
2321 const gboolean was_dualmask =
g->visual_mask;
2336 gtk_widget_set_tooltip_text(
g->demosaic_method_bayer, _(
"Bayer sensor demosaicing method, PPG and RCD are fast, AMaZE and LMMSE are slow.\nLMMSE is suited best for high ISO images.\ndual demosaicers double processing time."));
2340 gtk_widget_set_tooltip_text(
g->demosaic_method_xtrans, _(
"X-Trans sensor demosaicing method, Markesteijn 3-pass and frequency domain chroma are slow.\ndual demosaicers double processing time."));
2344 gtk_widget_set_tooltip_text(
g->median_thrs, _(
"threshold for edge-aware median.\nset to 0.0 to switch off\n"
2345 "set to 1.0 to ignore edges"));
2349 gtk_widget_set_tooltip_text(
g->dual_thrs, _(
"contrast threshold for dual demosaic.\nset to 0.0 for high frequency content\n"
2350 "set to 1.0 for flat content\ntoggle to visualize the mask"));
2354 g_signal_connect(G_OBJECT(
g->dual_thrs),
"quad-pressed", G_CALLBACK(
_visualize_callback), self);
2357 gtk_widget_set_tooltip_text(
g->lmmse_refine, _(
"LMMSE refinement steps. the median steps average the output,\nrefine adds some recalculation of red & blue channels"));
2360 gtk_widget_set_tooltip_text(
g->color_smoothing, _(
"how many post-demosaic smoothing passes.\nin downsample mode this sets the guided detail equalization iterations"));
2363 gtk_widget_set_tooltip_text(
g->greeneq, _(
"green channels matching method"));
2366 self->
widget = gtk_stack_new();
2367 gtk_stack_set_homogeneous(GTK_STACK(self->
widget),
FALSE);
2370 gtk_widget_set_tooltip_text(label_non_raw, _(
"demosaicing is only used for color raw images"));
2372 gtk_stack_add_named(GTK_STACK(self->
widget), label_non_raw,
"non_raw");
2373 gtk_stack_add_named(GTK_STACK(self->
widget), box_raw,
"raw");
static void error(char *msg)
void cleanup(dt_imageio_module_format_t *self)
static __DT_CLONE_TARGETS__ void green_equilibration_lavg(float *out, const float *const in, const int width, const int height, const uint32_t filters, const int x, const int y, const float thr)
static int green_equilibration_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)
static __DT_CLONE_TARGETS__ void green_equilibration_favg(float *out, const float *const in, const int width, const int height, const uint32_t filters, const int x, const int y)
static __DT_CLONE_TARGETS__ void color_smoothing(float *out, const dt_iop_roi_t *const roi_out, const int num_passes)
static int color_smoothing_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_out, const int passes)
void dt_bauhaus_slider_set_digits(GtkWidget *widget, int val)
gboolean dt_bauhaus_combobox_set_from_value(GtkWidget *widget, int value)
void dt_bauhaus_widget_set_quad_toggle(GtkWidget *widget, int toggle)
void dt_bauhaus_widget_set_quad_active(GtkWidget *widget, int active)
int dt_bauhaus_widget_get_quad_active(GtkWidget *widget)
void dt_bauhaus_combobox_remove_at(GtkWidget *widget, int pos)
void dt_bauhaus_widget_set_quad_paint(GtkWidget *widget, dt_bauhaus_quad_paint_f f, int paint_flags, void *paint_data)
static void blur_2D_Bspline(const float *const restrict in, float *const restrict out, float *const restrict tempbuf, const size_t width, const size_t height, const int mult, const gboolean clip_negatives)
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 float intp(const float a, const float b, const float c)
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)
__DT_CLONE_TARGETS__ int dt_colorspaces_conversion_matrices_rgb(const float adobe_XYZ_to_CAM[4][3], double out_RGB_to_CAM[4][3], double out_CAM_to_RGB[3][4], const float *embedded_matrix, double mul[4])
__DT_CLONE_TARGETS__ void dt_colorspaces_cygm_to_rgb(float *out, int num, double CAM_to_RGB[3][4])
static dt_aligned_pixel_t rgb
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)))
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_demosaic(const dt_image_t *img)
void dt_control_log(const char *msg,...)
void reset(dt_view_t *self)
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 dt_pixelpipe_cache_alloc_align_float_cache(pixels, id)
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...
static void dt_get_times(dt_times_t *t)
#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 __OMP_PARALLEL_FOR__(...)
#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)
@ DT_IOP_DEMOSAIC_MARKESTEIJN_3
@ DT_IOP_DEMOSAIC_RCD_VNG
@ DT_IOP_DEMOSAIC_MARKESTEIJN
@ DT_IOP_DEMOSAIC_PASSTHROUGH_COLOR
@ DT_IOP_DEMOSAIC_PASSTHR_MONOX
@ DT_IOP_DEMOSAIC_MARKEST3_VNG
@ DT_IOP_DEMOSAIC_AMAZE_VNG
@ DT_IOP_DEMOSAIC_DOWNSAMPLE
@ DT_IOP_DEMOSAIC_PASSTHR_COLORX
@ DT_IOP_DEMOSAIC_PASSTHROUGH_MONOCHROME
void distort_mask(struct dt_iop_module_t *self, const struct dt_dev_pixelpipe_t *pipe, struct dt_dev_pixelpipe_iop_t *piece, const float *const in, float *const out, const dt_iop_roi_t *const roi_in, const dt_iop_roi_t *const roi_out)
static int process_default_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 int demosaicing_method)
const char ** description(struct dt_iop_module_t *self)
void modify_roi_out(struct dt_iop_module_t *self, const struct dt_dev_pixelpipe_t *pipe, struct dt_dev_pixelpipe_iop_t *piece, dt_iop_roi_t *roi_out, const dt_iop_roi_t *const roi_in)
static gboolean _downsample_guided_laplacian_postfilter_cl(struct dt_iop_module_t *self, const dt_dev_pixelpipe_t *pipe, cl_mem dev_out, const dt_iop_roi_t *const roi_out, const int iterations)
static __DT_CLONE_TARGETS__ void _downsample_bayer_half_size(float *const out, const float *const in, const dt_iop_roi_t *const roi_out, const dt_iop_roi_t *const roi_in, const uint32_t filters, const gboolean is_4bayer, const double CAM_to_RGB[3][4])
Build one half-size RGB pixel from the 2x2 CFA block backing it.
void reload_defaults(dt_iop_module_t *module)
void amaze_demosaic_RT(const dt_dev_pixelpipe_iop_t *piece, const float *const in, float *out, const dt_iop_roi_t *const roi_in, const dt_iop_roi_t *const roi_out, const uint32_t filters)
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 __DT_CLONE_TARGETS__ void _downsample_xtrans_half_size(float *const out, const float *const in, const dt_iop_roi_t *const roi_out, const dt_iop_roi_t *const roi_in, const uint8_t(*const xtrans)[6])
Build one half-size RGB pixel from a 2x2 X-Trans block.
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 _downsample_guided_laplacian_postfilter(float *const out, const size_t width, const size_t height, const int iterations)
Denoise the half-size demosaic result by filtering its wavelet details.
dt_iop_demosaic_greeneq_t
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)
void gui_update(struct dt_iop_module_t *self)
void gui_init(struct dt_iop_module_t *self)
static gboolean _is_downsample_method(const dt_iop_demosaic_method_t method)
void gui_changed(dt_iop_module_t *self, GtkWidget *w, void *previous)
dt_iop_demosaic_quality_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 _downsample_guided_laplacian_apply(const float *const restrict HF, const float *const restrict coeff, const float *const restrict bias, const float *const restrict LF, float *const restrict reconstructed, const size_t width, const size_t height, const gboolean reset)
Apply the locally averaged affine RGB model to one high-frequency layer.
void cleanup_global(dt_iop_module_so_t *module)
static __DT_CLONE_TARGETS__ void _downsample_guided_laplacian_fit(const float *const restrict HF, float *const restrict coeff, float *const restrict bias, const size_t width, const size_t height)
Fit one local affine RGB model for the current high-frequency scale.
int default_colorspace(dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece)
void input_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__ float _downsample_xtrans_missing_colour(const float *const in, const dt_iop_roi_t *const roi_in, const int px, const int py, const uint8_t(*const xtrans)[6], const int colour)
Reconstruct one missing X-Trans colour from the nearest surrounding photosites.
#define DOWNSAMPLE_GUIDED_SCALES
__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 i, void *const o)
gboolean force_enable(struct dt_iop_module_t *self, const gboolean current_state)
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)
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)
void modify_roi_in(struct dt_iop_module_t *self, const struct dt_dev_pixelpipe_t *pipe, struct dt_dev_pixelpipe_iop_t *piece, const dt_iop_roi_t *roi_out, dt_iop_roi_t *roi_in)
int legacy_params(dt_iop_module_t *self, const void *const old_params, const int old_version, void *new_params, const int new_version)
#define dt_dev_pixelpipe_update_history_main(dev)
@ DT_DEV_PIXELPIPE_DISPLAY_PASSTHRU_MONO
@ DT_DEV_PIXELPIPE_DISPLAY_PASSTHRU
void dtgtk_cairo_paint_showmask(cairo_t *cr, gint x, gint y, gint w, gint h, gint flags, void *data)
static __DT_CLONE_TARGETS__ int dual_demosaic(const dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece, float *const restrict rgb_data, const float *const restrict raw_data, dt_iop_roi_t *const roi_out, const dt_iop_roi_t *const roi_in, const uint32_t filters, const uint8_t(*const xtrans)[6], const gboolean dual_mask, float dual_threshold)
gboolean dual_demosaic_cl(struct dt_iop_module_t *self, const dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece, cl_mem detail, cl_mem blend, cl_mem high_image, cl_mem low_image, cl_mem out, const int width, const int height, const int showmask)
#define DT_GUI_BOX_SPACING
static GtkWidget * dt_ui_label_new(const gchar *str)
@ DT_IMAGE_MONOCHROME_BAYER
dt_image_t * dt_image_cache_get(dt_image_cache_t *cache, const int32_t imgid, char mode)
void dt_image_cache_write_release(dt_image_cache_t *cache, dt_image_t *img, dt_image_cache_write_mode_t mode)
static void dt_iop_image_copy_by_size(float *const __restrict__ out, const float *const __restrict__ in, const size_t width, const size_t height, const size_t ch)
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)
#define dt_omploop_sfence()
#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)...
#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)
int dt_iop_clip_and_zoom_roi_cl(int devid, cl_mem dev_out, cl_mem dev_in, const dt_iop_roi_t *const roi_out, const dt_iop_roi_t *const roi_in)
const struct dt_interpolation * dt_interpolation_new(enum dt_interpolation_type type)
void dt_interpolation_resample_roi_1c(const struct dt_interpolation *itor, float *out, const dt_iop_roi_t *const roi_out, const float *const in, const dt_iop_roi_t *const roi_in)
@ DT_INTERPOLATION_USERPREF
const float *const const float coeff[3]
static void lmmse_demosaic(const dt_dev_pixelpipe_iop_t *piece, float *const restrict out, const float *const restrict in, dt_iop_roi_t *const roi_out, const dt_iop_roi_t *const roi_in, const uint32_t filters, const uint32_t mode, float *const restrict gamma_in, float *const restrict gamma_out)
float *const restrict const size_t k
static int process_markesteijn_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 gboolean smooth)
static __DT_CLONE_TARGETS__ void xtrans_markesteijn_interpolate(float *out, const float *const in, const dt_iop_roi_t *const roi_out, const dt_iop_roi_t *const roi_in, const uint8_t(*const xtrans)[6], const int passes)
static __DT_CLONE_TARGETS__ void xtrans_fdc_interpolate(struct dt_iop_module_t *self, float *out, const float *const in, const dt_iop_roi_t *const roi_out, const dt_iop_roi_t *const roi_in, const uint8_t(*const xtrans)[6])
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
static __DT_CLONE_TARGETS__ void passthrough_monochrome(float *out, const float *const in, dt_iop_roi_t *const roi_out, const dt_iop_roi_t *const roi_in)
static __DT_CLONE_TARGETS__ void passthrough_color(float *out, const float *const in, dt_iop_roi_t *const roi_out, const dt_iop_roi_t *const roi_in, const uint32_t filters, const uint8_t(*const xtrans)[6])
static __DT_CLONE_TARGETS__ int demosaic_ppg(float *const out, const float *const in, const dt_iop_roi_t *const roi_out, const dt_iop_roi_t *const roi_in, const uint32_t filters, const float thrs)
static int process_rcd_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 gboolean smooth)
static void rcd_demosaic(const dt_dev_pixelpipe_iop_t *piece, float *const restrict out, const float *const restrict in, dt_iop_roi_t *const roi_out, const dt_iop_roi_t *const roi_in, const uint32_t filters)
struct _GtkWidget GtkWidget
const float uint32_t state[4]
int32_t num_openmp_threads
struct dt_gui_gtk_t * gui
struct dt_image_cache_t * image_cache
dt_iop_buffer_dsc_t dsc_in
struct dt_iop_module_t *void * data
dt_dev_pixelpipe_type_t type
char camera_makermodel[128]
float d65_color_matrix[9]
float adobe_XYZ_to_CAM[4][3]
dt_iop_buffer_type_t datatype
dt_aligned_pixel_t processed_maximum
uint32_t demosaicing_method
int kernel_markesteijn_accu
int kernel_guided_laplacian_finalize
int kernel_markesteijn_solitary_green
int kernel_markesteijn_homo_quench
int kernel_green_eq_favg_apply
int kernel_rcd_write_output
int kernel_markesteijn_initial_copy
int kernel_markesteijn_final
int kernel_zoom_half_size
int kernel_green_eq_favg_reduce_second
int kernel_passthrough_color
int kernel_color_smoothing
int kernel_markesteijn_homo_max_corr
int kernel_markesteijn_interpolate_green
int kernel_markesteijn_convert_yuv
int kernel_bspline_vertical
int kernel_markesteijn_homo_threshold
int kernel_markesteijn_homo_sum
int kernel_markesteijn_green_minmax
int kernel_zoom_passthrough_monochrome
int kernel_markesteijn_recalculate_green
int kernel_zoom_half_size_xtrans
int kernel_vng_interpolate
int kernel_markesteijn_interpolate_twoxtwo
int kernel_markesteijn_homo_set
int kernel_guided_laplacian_coefficients
int kernel_rcd_border_redblue
int kernel_vng_green_equilibrate
int kernel_passthrough_monochrome
int kernel_bspline_horizontal
int kernel_guided_laplacian_normalize
int kernel_vng_border_interpolate
int kernel_markesteijn_red_and_blue
int kernel_markesteijn_differentiate
int kernel_markesteijn_homo_max
int kernel_rcd_border_green
int kernel_green_eq_favg_reduce_first
int kernel_zoom_third_size
int kernel_vng_lin_interpolate
int kernel_bspline_vertical_local
int kernel_bspline_horizontal_local
int kernel_markesteijn_zero
int kernel_write_blended_dual
int kernel_border_interpolate
int kernel_guided_laplacian_apply
GtkWidget * demosaic_method_xtrans
GtkWidget * color_smoothing
GtkWidget * demosaic_method_bayer
dt_iop_demosaic_method_t demosaicing_method
dt_iop_demosaic_greeneq_t green_eq
dt_iop_demosaic_smooth_t color_smoothing
dt_iop_demosaic_lmmse_t lmmse_refine
dt_iop_global_data_t * data
dt_iop_params_t * default_params
struct dt_develop_t * dev
dt_iop_gui_data_t * gui_data
dt_iop_global_data_t * global_data
Region of interest passed through the pixelpipe.
typedef double((*spd)(unsigned long int wavelength, double TempK))
static int process_vng_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 gboolean smooth, const int only_vng_linear)
static __DT_CLONE_TARGETS__ int vng_interpolate(float *out, const float *const in, const dt_iop_roi_t *const roi_out, const dt_iop_roi_t *const roi_in, const uint32_t filters, const uint8_t(*const xtrans)[6], const int only_vng_linear)