104 #define INLINE __inline
106 #define INLINE inline
109#define DEMOSAIC_XTRANS 1024
110#define DEMOSAIC_DUAL 2048
116#define XTRANS_SNAPPER 6
117#define DOWNSAMPLE_GUIDED_SCALES 1
256 return a * (b - c) + c;
292 const float *
const in,
296 const uint32_t filters);
313 return _(
"demosaic");
318 return dt_iop_set_description(self, _(
"reconstruct full RGB pixels from a sensor color filter array reading"),
320 _(
"linear, raw, scene-referred"),
322 _(
"linear, RGB, scene-referred"));
341 void *new_params,
const int new_version)
344 typedef struct dt_iop_demosaic_params_v3_t
351 } dt_iop_demosaic_params_v3_t;
353 if(old_version == 3 && new_version == 4)
355 dt_iop_demosaic_params_v3_t *o = (dt_iop_demosaic_params_v3_t *)old_params;
356 dt_iop_demosaic_params_v4_t *
n = (dt_iop_demosaic_params_v4_t *)new_params;
357 memcpy(
n, o,
sizeof *o);
358 n->dual_thrs = 0.20f;
362 if(old_version == 2 && new_version == 3)
368 n->color_smoothing = 0;
408 string =
"passthrough monochrome";
411 string =
"photosites";
420 string =
"RCD + VNG4";
423 string =
"AMaZE + VNG4";
426 string =
"VNG (xtrans)";
429 string =
"Markesteijn-1 (XTrans)";
432 string =
"Markesteijn-3 (XTrans)";
435 string =
"Markesteijn 3-pass + VNG";
438 string =
"Frequency Domain Chroma (XTrans)";
441 string =
"passthrough monochrome (XTrans)";
444 string =
"photosites (XTrans)";
447 string =
"downsample";
450 string =
"(unknown method)";
468 default:
return "none";
483 const dt_iop_roi_t *
const roi_in,
const uint32_t filters,
484 const gboolean is_4bayer,
const double CAM_to_RGB[3][4])
487 for(
int y = 0; y < roi_out->
height; y++)
489 for(
int x = 0;
x < roi_out->
width;
x++)
491 float *
const outc =
out + 4 * ((size_t)y * roi_out->
width +
x);
493 int samples[4] = { 0 };
494 const int px =
MIN(2 *
x, roi_in->
width - 1);
495 const int py =
MIN(2 * y, roi_in->
height - 1);
499 for(
int j = 0; j < 2; j++)
501 for(
int i = 0;
i < 2;
i++)
503 const int xx =
MIN(px +
i, roi_in->
width - 1);
504 const int yy =
MIN(py + j, roi_in->
height - 1);
505 const int c =
FC(yy, xx, filters);
506 cam[c] += in[(size_t)yy * roi_in->
width + xx];
511 for(
int c = 0; c < 4; c++)
512 if(samples[c] > 0) cam[c] /= (float)samples[c];
516 for(
int c = 0; c < 3; c++)
519 for(
int k = 0;
k < 4;
k++) outc[c] += CAM_to_RGB[c][
k] * cam[
k];
525 outc[1] = cam[
GREEN];
544 const int px,
const int py,
545 const uint8_t (*
const xtrans)[6],
const int colour)
547 const float cx = px + 0.5f;
548 const float cy = py + 0.5f;
549 const int xmin =
MAX(0, px - 3);
550 const int xmax =
MIN(roi_in->
width - 1, px + 4);
551 const int ymin =
MAX(0, py - 3);
552 const int ymax =
MIN(roi_in->
height - 1, py + 4);
554 float quadrant_value[4] = { 0.0f };
555 float quadrant_dist[4] = { INFINITY, INFINITY, INFINITY, INFINITY };
556 int quadrant_x[4] = { 0 };
557 int quadrant_y[4] = { 0 };
560 float nearest_value = 0.0f;
561 float nearest_dist = INFINITY;
565 for(
int yy = ymin; yy <= ymax; yy++)
567 for(
int xx = xmin; xx <= xmax; xx++)
569 if(
FCxtrans(yy, xx, roi_in, xtrans) != colour)
continue;
571 const float dx = xx - cx;
572 const float dy = yy - cy;
573 const float dist2 = dx * dx + dy * dy;
574 if(dist2 < nearest_dist)
576 nearest_dist = dist2;
577 nearest_value = in[(size_t)yy * roi_in->
width + xx];
580 const int quadrant = ((yy > cy) ? 2 : 0) + ((xx > cx) ? 1 : 0);
581 if(dist2 < quadrant_dist[quadrant])
583 quadrant_dist[quadrant] = dist2;
584 quadrant_value[quadrant] = in[(size_t)yy * roi_in->
width + xx];
585 quadrant_x[quadrant] = xx;
586 quadrant_y[quadrant] = yy;
587 quadrant_valid[quadrant] =
TRUE;
592 if(quadrant_valid[0] && quadrant_valid[1] && quadrant_valid[2] && quadrant_valid[3])
594 const float x_left = 0.5f * (quadrant_x[0] + quadrant_x[2]);
595 const float x_right = 0.5f * (quadrant_x[1] + quadrant_x[3]);
596 const float y_top = 0.5f * (quadrant_y[0] + quadrant_y[1]);
597 const float y_bottom = 0.5f * (quadrant_y[2] + quadrant_y[3]);
598 const float tx = CLAMP((cx - x_left) /
MAX(x_right - x_left, 1e-6f), 0.0f, 1.0f);
599 const float ty = CLAMP((cy - y_top) /
MAX(y_bottom - y_top, 1e-6f), 0.0f, 1.0f);
600 const float top = quadrant_value[0] + tx * (quadrant_value[1] - quadrant_value[0]);
601 const float bottom = quadrant_value[2] + tx * (quadrant_value[3] - quadrant_value[2]);
602 return top + ty * (bottom -
top);
607 for(
int q = 0; q < 4; q++)
609 if(!quadrant_valid[q])
continue;
610 sum += quadrant_value[q];
614 return (count > 0) ? sum / (float)count : nearest_value;
628 const uint8_t (*
const xtrans)[6])
631 for(
int y = 0; y < roi_out->
height; y++)
633 for(
int x = 0;
x < roi_out->
width;
x++)
635 float *
const outc =
out + 4 * ((size_t)y * roi_out->
width +
x);
637 int samples[3] = { 0 };
638 const int px =
MIN(2 *
x, roi_in->
width - 1);
639 const int py =
MIN(2 * y, roi_in->
height - 1);
643 for(
int j = 0; j < 2; j++)
645 for(
int i = 0;
i < 2;
i++)
647 const int xx =
MIN(px +
i, roi_in->
width - 1);
648 const int yy =
MIN(py + j, roi_in->
height - 1);
649 const int c =
FCxtrans(yy, xx, roi_in, xtrans);
650 rgb[c] += in[(size_t)yy * roi_in->
width + xx];
655 for(
int c = 0; c < 3; c++)
658 outc[c] =
rgb[c] / (float)samples[c];
682 float *
const restrict
coeff,
683 float *
const restrict bias,
686 const float eps = 1e-12f;
688 const dt_aligned_pixel_simd_t inv_patch =
dt_simd_set1(1.f / 25.f);
692 const float *
const row0 = HF + 4 * ((size_t)CLAMP((
int)
row - 2, 0, (int)
height - 1) *
width);
693 const float *
const row1 = HF + 4 * ((size_t)CLAMP((
int)
row - 1, 0, (int)
height - 1) *
width);
695 const float *
const row3 = HF + 4 * ((size_t)CLAMP((
int)
row + 1, 0, (int)
height - 1) *
width);
696 const float *
const row4 = HF + 4 * ((size_t)CLAMP((
int)
row + 2, 0, (int)
height - 1) *
width);
698 const int max_col = (int)
width - 1;
700 for(
size_t col = 0; col <
width; ++col)
702 dt_aligned_pixel_simd_t sum_rgb = zero;
703 dt_aligned_pixel_simd_t sum_rgb_guide = zero;
704 float sum_guide = 0.f;
705 float sum_guide_sq = 0.f;
707 = { 4 * CLAMP((
int)col - 2, 0, max_col),
708 4 * CLAMP((
int)col - 1, 0, max_col),
710 4 * CLAMP((
int)col + 1, 0, max_col),
711 4 * CLAMP((
int)col + 2, 0, max_col) };
718#if defined(__GNUC__) && !defined(__clang__)
723 const float *
const row_ptr = rows[jj];
724#if defined(__GNUC__) && !defined(__clang__)
729 const dt_aligned_pixel_simd_t sample = dt_load_simd_aligned(row_ptr + col_offsets[ii]);
730 const float guide = (sample[
RED] + sample[
GREEN] + sample[
BLUE]) / 3.f;
734 sum_guide_sq += guide * guide;
739 dt_aligned_pixel_simd_t means = sum_rgb * inv_patch;
740 const float guide_mean = sum_guide * (1.f / 25.f);
741 float variance = sum_guide_sq * (1.f / 25.f) - sqf(guide_mean);
742 dt_aligned_pixel_simd_t covariance = sum_rgb_guide * inv_patch - means *
dt_simd_set1(guide_mean);
744 covariance[
ALPHA] = 0.f;
746 if(variance < 0.f) variance = 0.f;
748 dt_aligned_pixel_simd_t slope = zero;
752 dt_aligned_pixel_simd_t intercept = means - slope *
dt_simd_set1(guide_mean);
753 intercept[
ALPHA] = 0.f;
771 const float *
const restrict
coeff,
772 const float *
const restrict bias,
773 const float *
const restrict LF,
774 float *
const restrict reconstructed,
776 const gboolean
reset)
781 for(
size_t col = 0; col <
width; ++col)
783 const size_t index = 4 * (
row *
width + col);
784 const dt_aligned_pixel_simd_t hf = dt_load_simd_aligned(HF + index);
786 dt_aligned_pixel_simd_t filtered = (dt_load_simd_aligned(
coeff + index) * guide
787 + dt_load_simd_aligned(bias + index))
788 * dt_load_simd_aligned(LF + index);
790 if(!
reset) filtered += dt_load_simd_aligned(reconstructed + index);
791 filtered[
ALPHA] = 0.f;
812 const int iterations)
814 if(iterations <= 0)
return 0;
826 const float *restrict residual =
out;
835 for(
int iteration = 0; iteration < iterations; ++iteration)
841 const int mult = 1 << s;
842 const float *restrict buffer_in;
843 float *restrict buffer_out;
853 buffer_out = LF_even;
867 for(
size_t col = 0; col <
width; ++col)
869 const size_t index = 4 * (
row *
width + col);
870 dt_aligned_pixel_simd_t lf = dt_load_simd_aligned(buffer_out + index);
871 lf[
RED] = fmaxf(lf[
RED], 1e-8f);
876 dt_aligned_pixel_simd_t normalized = dt_load_simd_aligned(HF + index) / lf;
877 normalized[
ALPHA] = 0.f;
891 residual = buffer_out;
894 const gboolean last_iteration = (iteration == iterations - 1);
898 for(
size_t col = 0; col <
width; ++col)
900 const size_t index = 4 * (
row *
width + col);
901 dt_aligned_pixel_simd_t pixel
902 = dt_simd_max_zero(dt_load_simd_aligned(reconstructed + index)
903 + dt_load_simd_aligned(residual + index));
907 dt_store_simd_nontemporal(
out + index, pixel);
929 const float *
const in,
float *
const out,
const dt_iop_roi_t *
const roi_in,
984 .backtransform = NULL,
1044 const void *
const i,
void *
const o)
1050 dt_times_t start_time = { 0 }, end_time = { 0 };
1070 const uint8_t(*
const xtrans_raw)[6] = (
const uint8_t(*
const)[6])piece->
dsc_in.
xtrans;
1078 gboolean showmask =
FALSE;
1082 if(
g) showmask = (
g->visual_mask);
1091 "[demosaic] CPU pipe %p (%s) thread %lu piece %p roi_in=(%d,%d) %dx%d dsc_in.filters=0x%x -> filters=0x%x xtrans_raw=%p method=%s\n",
1092 (
void *)pipe, _pipe_type_string(pipe->
type), (
unsigned long)pthread_self(), (
void *)piece,
1094 piece->
dsc_in.
filters, filters, (
void *)xtrans_raw, method2string(demosaicing_method));
1096 const float *
const pixels = (
float *)
i;
1119 else if(filters == 9u)
1134 float *in = (
float *)pixels;
1146 roi_in->
x, roi_in->
y);
1160 roi_in->
x, roi_in->
y);
1208 for(
int j = 0; j < 65536; j++)
1210 const double x = (
double)j / 65535.0;
1235 const float mpixels = (roo.
width * roo.
height) / 1.0e6;
1237 const float tclock = end_time.clock - start_time.
clock;
1238 const float uclock = end_time.user - start_time.
user;
1239 fprintf(stderr,
" [demosaic] process CPU `%s' did %.2fmpix, %.4f secs (%.4f CPU), %.2f pix/us\n",
1240 method2string(demosaicing_method & ~
DEMOSAIC_DUAL), mpixels, tclock, uclock, mpixels / tclock);
1259 const dt_iop_roi_t *
const roi_out,
const int demosaicing_method)
1264 const int devid = pipe->
devid;
1266 cl_mem dev_aux = NULL;
1267 cl_mem dev_tmp = NULL;
1268 cl_mem dev_med = NULL;
1269 cl_mem dev_green_eq = NULL;
1288 dev_in = dev_green_eq;
1302 if(err != CL_SUCCESS)
goto error;
1316 if(err != CL_SUCCESS)
goto error;
1324 const int myborder = 3;
1334 if(err != CL_SUCCESS)
goto error;
1344 .cellsize = 1 *
sizeof(float), .overhead = 0,
1345 .sizex = 1 << 8, .sizey = 1 << 8 };
1351 size_t local[3] = { locopt.
sizex, locopt.
sizey, 1 };
1360 sizeof(
float) * (locopt.
sizex + 4) * (locopt.
sizey + 4), NULL);
1362 if(err != CL_SUCCESS)
goto error;
1371 .cellsize =
sizeof(float) * 1, .overhead = 0,
1372 .sizex = 1 << 8, .sizey = 1 << 8 };
1378 size_t local[3] = { locopt.
sizex, locopt.
sizey, 1 };
1386 sizeof(
float) * (locopt.
sizex + 2*3) * (locopt.
sizey + 2*3), NULL);
1389 if(err != CL_SUCCESS)
goto error;
1395 .cellsize = 4 *
sizeof(float), .overhead = 0,
1396 .sizex = 1 << 8, .sizey = 1 << 8 };
1402 size_t local[3] = { locopt.
sizex, locopt.
sizey, 1 };
1410 sizeof(
float) * 4 * (locopt.
sizex + 2) * (locopt.
sizey + 2), NULL);
1413 if(err != CL_SUCCESS)
goto error;
1421 dev_aux = dev_green_eq = dev_tmp = dev_med = NULL;
1445 const int iterations)
1447 if(iterations <= 0)
return TRUE;
1450 const int devid = pipe->
devid;
1453 const int clip_negatives = 1;
1454 const int keep_signed = 0;
1455 const int dense_mult = 1;
1458 cl_mem LF_even = NULL;
1459 cl_mem LF_odd = NULL;
1461 cl_mem
coeff = NULL;
1463 cl_mem coeff_tmp = NULL;
1464 cl_mem reconstructed_a = NULL;
1465 cl_mem reconstructed_b = NULL;
1466 cl_mem residual = NULL;
1467 cl_mem reconstructed_read = NULL;
1468 cl_mem reconstructed_write = NULL;
1469 cl_mem reconstructed_final = NULL;
1484 for(
int iteration = 0; iteration < iterations; ++iteration)
1486 reconstructed_read = reconstructed_a;
1487 reconstructed_write = reconstructed_b;
1488 reconstructed_final = NULL;
1493 const int mult = 1 << s;
1494 const int first_scale = (s == 0);
1500 buffer_in = dev_out;
1501 buffer_out = LF_odd;
1506 buffer_out = LF_even;
1510 buffer_in = LF_even;
1511 buffer_out = LF_odd;
1516 .yoffset = 0, .yfactor = 1,
1517 .cellsize = 4 *
sizeof(float), .overhead = 0,
1518 .sizex = 1 << 16, .sizey = 1 };
1520 hblocksize = hlocopt.
sizex;
1527 const size_t horizontal_local[3] = { hblocksize, 1, 1 };
1535 (hblocksize + 4 * mult) * 4 *
sizeof(
float), NULL);
1537 horizontal_sizes, horizontal_local);
1549 if(err != CL_SUCCESS)
goto error;
1553 .yoffset = 2 * mult, .yfactor = 1,
1554 .cellsize = 4 *
sizeof(float), .overhead = 0,
1555 .sizex = 1, .sizey = 1 << 16 };
1557 vblocksize = vlocopt.
sizey;
1564 const size_t vertical_local[3] = { 1, vblocksize, 1 };
1572 (vblocksize + 4 * mult) * 4 *
sizeof(
float), NULL);
1574 vertical_sizes, vertical_local);
1586 if(err != CL_SUCCESS)
goto error;
1594 if(err != CL_SUCCESS)
goto error;
1602 if(err != CL_SUCCESS)
goto error;
1611 if(err != CL_SUCCESS)
goto error;
1620 if(err != CL_SUCCESS)
goto error;
1629 if(err != CL_SUCCESS)
goto error;
1638 if(err != CL_SUCCESS)
goto error;
1650 if(err != CL_SUCCESS)
goto error;
1652 residual = buffer_out;
1653 reconstructed_final = reconstructed_write;
1654 cl_mem tmp = reconstructed_read;
1655 reconstructed_read = reconstructed_write;
1656 reconstructed_write = tmp;
1665 if(err != CL_SUCCESS)
goto error;
1692 cl_mem dev_in, cl_mem dev_out)
1696 dt_times_t start_time = { 0 }, end_time = { 0 };
1711 gboolean showmask =
FALSE;
1715 if(
g) showmask = (
g->visual_mask);
1724 "[demosaic] CL pipe %p (%s) thread %lu piece %p devid=%d roi_in=(%d,%d) %dx%d dsc_in.filters=0x%x -> filters=0x%x method=%s\n",
1725 (
void *)pipe, _pipe_type_string(pipe->
type), (
unsigned long)pthread_self(), (
void *)piece,
1727 piece->
dsc_in.
filters, filters, method2string(demosaicing_method));
1729 cl_mem high_image = NULL;
1730 cl_mem low_image = NULL;
1731 cl_mem blend = NULL;
1732 cl_mem details = NULL;
1733 cl_mem dev_aux = NULL;
1734 cl_mem dev_xtrans = NULL;
1736 const int devid = pipe->
devid;
1737 gboolean retval =
FALSE;
1745 if(!
process_default_cl(self, pipe, piece, dev_in, dev_out, roi_in, roi_out, demosaicing_method))
return FALSE;
1769 if(err != CL_SUCCESS)
goto finish;
1797 if(err != CL_SUCCESS)
goto finish;
1811 if(!
process_rcd_cl(self, pipe, piece, dev_in, high_image, roi_in, roi_in,
FALSE))
goto finish;
1838 dt_print(
DT_DEBUG_OPENCL,
"[opencl_demosaic] demosaicing method '%s' not yet supported by opencl code\n", method2string(demosaicing_method));
1844 const float mpixels = (roi_in->
width * roi_in->
height) / 1.0e6;
1846 const float tclock = end_time.clock - start_time.
clock;
1847 const float uclock = end_time.user - start_time.
user;
1848 fprintf(stderr,
" [demosaic] process GPU `%s' did %.2fmpix, %.4f secs (%.4f CPU), %.2f pix/us\n",
1849 method2string(demosaicing_method & ~
DEMOSAIC_DUAL), mpixels, tclock, uclock, mpixels / tclock);
1887 retval =
dual_demosaic_cl(self, pipe, piece, details, blend, high_image, low_image, dev_aux,
width,
height, showmask);
1893 fprintf(stderr,
" [demosaic] GPU dual blending %.4f secs (%.4f CPU)\n", end_time.clock - start_time.
clock, end_time.user - start_time.
user);
1900 if(err != CL_SUCCESS)
1911 if(!retval && dual)
dt_control_log(_(
"[dual demosaic_cl] internal problem"));
1943 tiling->factor = 1.0f + ioratio;
1944 tiling->factor += fmax(1.0f + greeneq, smooth);
1959 tiling->factor = 1.0f + ioratio;
1960 tiling->factor += ndir * 1.0f
1965 tiling->factor += fmax(1.0f + greeneq, smooth);
1970 tiling->overlap = overlap;
1974 tiling->factor = 1.0f + ioratio;
1975 tiling->factor += fmax(1.0f + greeneq, smooth);
1985 tiling->factor = 1.0f + ioratio;
1986 tiling->factor += fmax(1.0f + greeneq, smooth);
1996 tiling->factor = 1.0f + ioratio;
1997 tiling->factor += fmax(1.0f + greeneq, smooth);
2018 const int program = 0;
2034 const int other = 14;
2047 const int markesteijn = 16;
2081 const int wavelets = 35;
2168 dt_iop_fmt_log(self,
"force_enable: class=%s needs_demosaic=%d current=%d -> %d",
2181 d->green_eq =
p->green_eq;
2182 d->color_smoothing =
p->color_smoothing;
2183 d->median_thrs =
p->median_thrs;
2184 d->dual_thrs =
p->dual_thrs;
2185 d->lmmse_refine =
p->lmmse_refine;
2206 d->median_thrs = 0.0f;
2211 d->color_smoothing = 0;
2212 d->dual_thrs = 0.0f;
2217 d->dual_thrs = 0.0f;
2221 d->color_smoothing = 0;
2223 d->demosaicing_method = use_method;
2226 switch(
d->demosaicing_method)
2292 NULL,
d->CAM_to_RGB,
2296 fprintf(stderr,
"[colorspaces] `%s' color matrix not found for 4bayer image!\n", camera);
2297 dt_control_log(_(
"`%s' color matrix not found for 4bayer image!"), camera);
2301 dt_iop_fmt_log(self,
"commit: class=%s in(filters=%u ch=%i) method=%d passthrough=%d -> enabled=%d cl_ready=%d",
2330 module->hide_enable_button = 1;
2334 module->default_enabled = dt_image_needs_demosaic(&module->dev->image_storage);
2335 dt_iop_fmt_log(module,
"reload_defaults: class=%s needs_demosaic=%d filters=%u mono=%d method=%d -> default_enabled=%d",
2362 const gboolean isdual = !isdownsample && (use_method &
DEMOSAIC_DUAL);
2369 gtk_widget_set_visible(
g->demosaic_method_bayer, bayer);
2370 gtk_widget_set_visible(
g->demosaic_method_xtrans, !bayer);
2376 gtk_widget_set_visible(
g->median_thrs, bayer && isppg);
2377 gtk_widget_set_visible(
g->greeneq, !passing && !isdownsample);
2378 gtk_widget_set_visible(
g->color_smoothing, !passing && !isdual);
2379 gtk_widget_set_visible(
g->dual_thrs, isdual);
2380 gtk_widget_set_visible(
g->lmmse_refine, islmmse);
2388 img->
flags &= ~DT_IMAGE_MONOCHROME_BAYER;
2417 const gboolean was_dualmask =
g->visual_mask;
2432 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."));
2436 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."));
2440 gtk_widget_set_tooltip_text(
g->median_thrs, _(
"threshold for edge-aware median.\nset to 0.0 to switch off\n"
2441 "set to 1.0 to ignore edges"));
2445 gtk_widget_set_tooltip_text(
g->dual_thrs, _(
"contrast threshold for dual demosaic.\nset to 0.0 for high frequency content\n"
2446 "set to 1.0 for flat content\ntoggle to visualize the mask"));
2450 g_signal_connect(G_OBJECT(
g->dual_thrs),
"quad-pressed", G_CALLBACK(
_visualize_callback), self);
2453 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"));
2456 gtk_widget_set_tooltip_text(
g->color_smoothing, _(
"how many post-demosaic smoothing passes.\nin downsample mode this sets the guided detail equalization iterations"));
2459 gtk_widget_set_tooltip_text(
g->greeneq, _(
"green channels matching method"));
2466 gtk_widget_set_tooltip_text(label_non_raw, _(
"demosaicing is only used for color raw images"));
2468 gtk_stack_add_named(GTK_STACK(self->
gui->
widget), label_non_raw,
"non_raw");
2469 gtk_stack_add_named(GTK_STACK(self->
gui->
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, const size_t width, const size_t height)
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)
typedef void((*dt_cache_allocate_t)(void *userdata, dt_cache_entry_t *entry))
static float intp(const float a, const float b, const float c)
return vector dt_simd_set1(valid ?(scaling+NORM_MIN) :NORM_MIN)
const float *const const float coeff[3]
__DT_CLONE_TARGETS__ int dt_colorspaces_conversion_matrices_rgb(const float *adobe_XYZ_to_CAM, double(*out_RGB_to_CAM)[3], double(*out_CAM_to_RGB)[4], const float *embedded_matrix, double *mul)
Compute the sRGB->camera and camera->sRGB matrices, and the default white balance multipliers.
__DT_CLONE_TARGETS__ void dt_colorspaces_cygm_to_rgb(float *out, int num, double CAM_to_RGB[3][4])
Convert a 4-channel CYGM buffer to RGB, in place.
The colour-profile module's API: which profiles exist, and how to apply one.
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
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)))
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)
int dt_get_num_openmp_threads(void)
Number of OpenMP threads the application decided to use.
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)
static const dt_geometry_vtable_t _demosaic_geometry_vtable
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)
gboolean geometry_record(dt_iop_module_t *self, const void *params, dt_geometry_record_t *record)
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)
static void _demosaic_geometry_map_size(const void *data, const dt_iop_roi_t *const in, dt_iop_roi_t *out)
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)
static void _demosaic_map_size(const gboolean downsamples, const dt_iop_roi_t *const roi_in, dt_iop_roi_t *roi_out)
Input rect -> output rect. THE size evaluator: modify_roi_out() below and the geometry service's reco...
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
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)
Where things are on the image, answered without a pipeline.
@ DT_IMAGE_MONOCHROME_BAYER
void dt_image_cache_write_release(dt_image_t *img, dt_image_cache_write_mode_t mode)
dt_image_t * dt_image_cache_get(const int32_t imgid, char 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)
uint32_t dt_dev_get_roi_filters(const dt_dev_pixelpipe_iop_t *const piece, const dt_iop_roi_t *const roi_in)
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_iop_fmt_log(module, fmt,...)
Debug helper to trace a module's input-format-driven decisions on the -d pipe channel (DT_DEBUG_PIPE)...
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)
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
GtkWidget * dt_ui_label_new(const gchar *str)
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)
_lib_location_type_t type
int32_t dt_get_debug_flags(void)
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
#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 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])
The detail-mask pixel math: a Scharr-style detail estimate over a raw or scene-referred buffer,...
#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.
static void dt_free_gpointer(gpointer ptr)
g_free() one pointer, with the signature GDestroyNotify wants.
#define dt_free(ptr)
g_free() ptr and set it to NULL, skipping both if it is already NULL.
#define DT_MODULE_INTROSPECTION(MODVER, PARAMSTYPE)
DT_MODULE() for a module whose params struct is introspected.
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
#define dt_omploop_sfence()
#define __OMP_PARALLEL_FOR__(...)
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])
@ DT_DEV_PIXELPIPE_THUMBNAIL
@ DT_DEV_PIXELPIPE_EXPORT
@ DT_DEV_PIXELPIPE_PREVIEW
#define dt_pixelpipe_cache_alloc_align_float_cache(pixels, id)
#define dt_pixelpipe_cache_free_align(mem)
#define dt_pixelpipe_cache_alloc_align_float(pixels, pipe)
#define dt_pixelpipe_cache_alloc_perthread_float(n, padded_size)
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)
static const dt_aligned_pixel_simd_t const dt_aligned_pixel_simd_t row1
DT_ALIGNED_PIXEL float dt_aligned_pixel_t[4]
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 const dt_aligned_pixel_simd_t const dt_aligned_pixel_simd_t row2
static const dt_aligned_pixel_simd_t row0
const float uint32_t state[4]
dt_iop_buffer_dsc_t dsc_in
struct dt_iop_module_t *void * data
dt_dev_pixelpipe_type_t type
One module instance's contribution, as data.
const dt_geometry_vtable_t * vtable
void(* free_data)(void *data)
A module's geometry, evaluated. Pure functions of the record's own data.
void(* map_size)(const void *data, const dt_iop_roi_t *const in, dt_iop_roi_t *out)
Full-resolution input rect -> output rect. Mirrors modify_roi_out() at scale 1.
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_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__
typedef double((*spd)(unsigned long int wavelength, double TempK))
static void dt_get_times(dt_times_t *t)
Telling the user something happened.
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)