95 #define INLINE __inline
100#define DEMOSAIC_XTRANS 1024
101#define DEMOSAIC_DUAL 2048
107#define XTRANS_SNAPPER 6
108#define DOWNSAMPLE_GUIDED_SCALES 1
247 return a * (b - c) + c;
283 const float *
const in,
287 const uint32_t filters);
304 return _(
"demosaic");
309 return dt_iop_set_description(self, _(
"reconstruct full RGB pixels from a sensor color filter array reading"),
311 _(
"linear, raw, scene-referred"),
313 _(
"linear, RGB, scene-referred"));
332 void *new_params,
const int new_version)
335 typedef struct dt_iop_demosaic_params_v3_t
342 } dt_iop_demosaic_params_v3_t;
344 if(old_version == 3 && new_version == 4)
346 dt_iop_demosaic_params_v3_t *o = (dt_iop_demosaic_params_v3_t *)old_params;
347 dt_iop_demosaic_params_v4_t *
n = (dt_iop_demosaic_params_v4_t *)new_params;
348 memcpy(
n, o,
sizeof *o);
349 n->dual_thrs = 0.20f;
353 if(old_version == 2 && new_version == 3)
359 n->color_smoothing = 0;
399 string =
"passthrough monochrome";
402 string =
"photosites";
411 string =
"RCD + VNG4";
414 string =
"AMaZE + VNG4";
417 string =
"VNG (xtrans)";
420 string =
"Markesteijn-1 (XTrans)";
423 string =
"Markesteijn-3 (XTrans)";
426 string =
"Markesteijn 3-pass + VNG";
429 string =
"Frequency Domain Chroma (XTrans)";
432 string =
"passthrough monochrome (XTrans)";
435 string =
"photosites (XTrans)";
438 string =
"downsample";
441 string =
"(unknown method)";
459 default:
return "none";
474 const dt_iop_roi_t *
const roi_in,
const uint32_t filters,
475 const gboolean is_4bayer,
const double CAM_to_RGB[3][4])
478 for(
int y = 0; y < roi_out->
height; y++)
480 for(
int x = 0;
x < roi_out->
width;
x++)
482 float *
const outc =
out + 4 * ((size_t)y * roi_out->
width +
x);
484 int samples[4] = { 0 };
485 const int px =
MIN(2 *
x, roi_in->
width - 1);
486 const int py =
MIN(2 * y, roi_in->
height - 1);
490 for(
int j = 0; j < 2; j++)
492 for(
int i = 0;
i < 2;
i++)
494 const int xx =
MIN(px +
i, roi_in->
width - 1);
495 const int yy =
MIN(py + j, roi_in->
height - 1);
496 const int c =
FC(yy, xx, filters);
497 cam[c] += in[(size_t)yy * roi_in->
width + xx];
502 for(
int c = 0; c < 4; c++)
503 if(samples[c] > 0) cam[c] /= (float)samples[c];
507 for(
int c = 0; c < 3; c++)
510 for(
int k = 0;
k < 4;
k++) outc[c] += CAM_to_RGB[c][
k] * cam[
k];
516 outc[1] = cam[
GREEN];
535 const int px,
const int py,
536 const uint8_t (*
const xtrans)[6],
const int colour)
538 const float cx = px + 0.5f;
539 const float cy = py + 0.5f;
540 const int xmin =
MAX(0, px - 3);
541 const int xmax =
MIN(roi_in->
width - 1, px + 4);
542 const int ymin =
MAX(0, py - 3);
543 const int ymax =
MIN(roi_in->
height - 1, py + 4);
545 float quadrant_value[4] = { 0.0f };
546 float quadrant_dist[4] = { INFINITY, INFINITY, INFINITY, INFINITY };
547 int quadrant_x[4] = { 0 };
548 int quadrant_y[4] = { 0 };
551 float nearest_value = 0.0f;
552 float nearest_dist = INFINITY;
556 for(
int yy = ymin; yy <= ymax; yy++)
558 for(
int xx = xmin; xx <= xmax; xx++)
560 if(
FCxtrans(yy, xx, roi_in, xtrans) != colour)
continue;
562 const float dx = xx - cx;
563 const float dy = yy - cy;
564 const float dist2 = dx * dx + dy * dy;
565 if(dist2 < nearest_dist)
567 nearest_dist = dist2;
568 nearest_value = in[(size_t)yy * roi_in->
width + xx];
571 const int quadrant = ((yy > cy) ? 2 : 0) + ((xx > cx) ? 1 : 0);
572 if(dist2 < quadrant_dist[quadrant])
574 quadrant_dist[quadrant] = dist2;
575 quadrant_value[quadrant] = in[(size_t)yy * roi_in->
width + xx];
576 quadrant_x[quadrant] = xx;
577 quadrant_y[quadrant] = yy;
578 quadrant_valid[quadrant] =
TRUE;
583 if(quadrant_valid[0] && quadrant_valid[1] && quadrant_valid[2] && quadrant_valid[3])
585 const float x_left = 0.5f * (quadrant_x[0] + quadrant_x[2]);
586 const float x_right = 0.5f * (quadrant_x[1] + quadrant_x[3]);
587 const float y_top = 0.5f * (quadrant_y[0] + quadrant_y[1]);
588 const float y_bottom = 0.5f * (quadrant_y[2] + quadrant_y[3]);
589 const float tx = CLAMP((cx - x_left) /
MAX(x_right - x_left, 1e-6f), 0.0f, 1.0f);
590 const float ty = CLAMP((cy - y_top) /
MAX(y_bottom - y_top, 1e-6f), 0.0f, 1.0f);
591 const float top = quadrant_value[0] + tx * (quadrant_value[1] - quadrant_value[0]);
592 const float bottom = quadrant_value[2] + tx * (quadrant_value[3] - quadrant_value[2]);
593 return top + ty * (bottom -
top);
598 for(
int q = 0; q < 4; q++)
600 if(!quadrant_valid[q])
continue;
601 sum += quadrant_value[q];
605 return (count > 0) ? sum / (float)count : nearest_value;
619 const uint8_t (*
const xtrans)[6])
622 for(
int y = 0; y < roi_out->
height; y++)
624 for(
int x = 0;
x < roi_out->
width;
x++)
626 float *
const outc =
out + 4 * ((size_t)y * roi_out->
width +
x);
628 int samples[3] = { 0 };
629 const int px =
MIN(2 *
x, roi_in->
width - 1);
630 const int py =
MIN(2 * y, roi_in->
height - 1);
634 for(
int j = 0; j < 2; j++)
636 for(
int i = 0;
i < 2;
i++)
638 const int xx =
MIN(px +
i, roi_in->
width - 1);
639 const int yy =
MIN(py + j, roi_in->
height - 1);
640 const int c =
FCxtrans(yy, xx, roi_in, xtrans);
641 rgb[c] += in[(size_t)yy * roi_in->
width + xx];
646 for(
int c = 0; c < 3; c++)
649 outc[c] =
rgb[c] / (float)samples[c];
673 float *
const restrict
coeff,
674 float *
const restrict bias,
677 const float eps = 1e-12f;
679 const dt_aligned_pixel_simd_t inv_patch =
dt_simd_set1(1.f / 25.f);
683 const float *
const row0 = HF + 4 * ((size_t)CLAMP((
int)
row - 2, 0, (int)
height - 1) *
width);
684 const float *
const row1 = HF + 4 * ((size_t)CLAMP((
int)
row - 1, 0, (int)
height - 1) *
width);
686 const float *
const row3 = HF + 4 * ((size_t)CLAMP((
int)
row + 1, 0, (int)
height - 1) *
width);
687 const float *
const row4 = HF + 4 * ((size_t)CLAMP((
int)
row + 2, 0, (int)
height - 1) *
width);
689 const int max_col = (int)
width - 1;
691 for(
size_t col = 0; col <
width; ++col)
693 dt_aligned_pixel_simd_t sum_rgb = zero;
694 dt_aligned_pixel_simd_t sum_rgb_guide = zero;
695 float sum_guide = 0.f;
696 float sum_guide_sq = 0.f;
698 = { 4 * CLAMP((
int)col - 2, 0, max_col),
699 4 * CLAMP((
int)col - 1, 0, max_col),
701 4 * CLAMP((
int)col + 1, 0, max_col),
702 4 * CLAMP((
int)col + 2, 0, max_col) };
709#if defined(__GNUC__) && !defined(__clang__)
714 const float *
const row_ptr = rows[jj];
715#if defined(__GNUC__) && !defined(__clang__)
720 const dt_aligned_pixel_simd_t sample = dt_load_simd_aligned(row_ptr + col_offsets[ii]);
721 const float guide = (sample[
RED] + sample[
GREEN] + sample[
BLUE]) / 3.f;
725 sum_guide_sq += guide * guide;
730 dt_aligned_pixel_simd_t means = sum_rgb * inv_patch;
731 const float guide_mean = sum_guide * (1.f / 25.f);
732 float variance = sum_guide_sq * (1.f / 25.f) - sqf(guide_mean);
733 dt_aligned_pixel_simd_t covariance = sum_rgb_guide * inv_patch - means *
dt_simd_set1(guide_mean);
735 covariance[
ALPHA] = 0.f;
737 if(variance < 0.f) variance = 0.f;
739 dt_aligned_pixel_simd_t slope = zero;
743 dt_aligned_pixel_simd_t intercept = means - slope *
dt_simd_set1(guide_mean);
744 intercept[
ALPHA] = 0.f;
762 const float *
const restrict
coeff,
763 const float *
const restrict bias,
764 const float *
const restrict LF,
765 float *
const restrict reconstructed,
767 const gboolean
reset)
772 for(
size_t col = 0; col <
width; ++col)
774 const size_t index = 4 * (
row *
width + col);
775 const dt_aligned_pixel_simd_t hf = dt_load_simd_aligned(HF + index);
777 dt_aligned_pixel_simd_t filtered = (dt_load_simd_aligned(
coeff + index) * guide
778 + dt_load_simd_aligned(bias + index))
779 * dt_load_simd_aligned(LF + index);
781 if(!
reset) filtered += dt_load_simd_aligned(reconstructed + index);
782 filtered[
ALPHA] = 0.f;
803 const int iterations)
805 if(iterations <= 0)
return 0;
817 const float *restrict residual =
out;
826 for(
int iteration = 0; iteration < iterations; ++iteration)
832 const int mult = 1 << s;
833 const float *restrict buffer_in;
834 float *restrict buffer_out;
844 buffer_out = LF_even;
858 for(
size_t col = 0; col <
width; ++col)
860 const size_t index = 4 * (
row *
width + col);
861 dt_aligned_pixel_simd_t lf = dt_load_simd_aligned(buffer_out + index);
862 lf[
RED] = fmaxf(lf[
RED], 1e-8f);
867 dt_aligned_pixel_simd_t normalized = dt_load_simd_aligned(HF + index) / lf;
868 normalized[
ALPHA] = 0.f;
882 residual = buffer_out;
885 const gboolean last_iteration = (iteration == iterations - 1);
889 for(
size_t col = 0; col <
width; ++col)
891 const size_t index = 4 * (
row *
width + col);
892 dt_aligned_pixel_simd_t pixel
893 = dt_simd_max_zero(dt_load_simd_aligned(reconstructed + index)
894 + dt_load_simd_aligned(residual + index));
898 dt_store_simd_nontemporal(
out + index, pixel);
920 const float *
const in,
float *
const out,
const dt_iop_roi_t *
const roi_in,
988 const void *
const i,
void *
const o)
994 dt_times_t start_time = { 0 }, end_time = { 0 };
1014 const uint8_t(*
const xtrans_raw)[6] = (
const uint8_t(*
const)[6])piece->
dsc_in.
xtrans;
1022 gboolean showmask =
FALSE;
1026 if(
g) showmask = (
g->visual_mask);
1035 "[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",
1036 (
void *)pipe, _pipe_type_string(pipe->
type), (
unsigned long)pthread_self(), (
void *)piece,
1038 piece->
dsc_in.
filters, filters, (
void *)xtrans_raw, method2string(demosaicing_method));
1040 const float *
const pixels = (
float *)
i;
1063 else if(filters == 9u)
1078 float *in = (
float *)pixels;
1090 roi_in->
x, roi_in->
y);
1104 roi_in->
x, roi_in->
y);
1152 for(
int j = 0; j < 65536; j++)
1154 const double x = (
double)j / 65535.0;
1179 const float mpixels = (roo.
width * roo.
height) / 1.0e6;
1181 const float tclock = end_time.clock - start_time.
clock;
1182 const float uclock = end_time.user - start_time.
user;
1183 fprintf(stderr,
" [demosaic] process CPU `%s' did %.2fmpix, %.4f secs (%.4f CPU), %.2f pix/us\n",
1184 method2string(demosaicing_method & ~
DEMOSAIC_DUAL), mpixels, tclock, uclock, mpixels / tclock);
1203 const dt_iop_roi_t *
const roi_out,
const int demosaicing_method)
1208 const int devid = pipe->
devid;
1210 cl_mem dev_aux = NULL;
1211 cl_mem dev_tmp = NULL;
1212 cl_mem dev_med = NULL;
1213 cl_mem dev_green_eq = NULL;
1232 dev_in = dev_green_eq;
1246 if(err != CL_SUCCESS)
goto error;
1260 if(err != CL_SUCCESS)
goto error;
1268 const int myborder = 3;
1278 if(err != CL_SUCCESS)
goto error;
1288 .cellsize = 1 *
sizeof(float), .overhead = 0,
1289 .sizex = 1 << 8, .sizey = 1 << 8 };
1295 size_t local[3] = { locopt.
sizex, locopt.
sizey, 1 };
1304 sizeof(
float) * (locopt.
sizex + 4) * (locopt.
sizey + 4), NULL);
1306 if(err != CL_SUCCESS)
goto error;
1315 .cellsize =
sizeof(float) * 1, .overhead = 0,
1316 .sizex = 1 << 8, .sizey = 1 << 8 };
1322 size_t local[3] = { locopt.
sizex, locopt.
sizey, 1 };
1330 sizeof(
float) * (locopt.
sizex + 2*3) * (locopt.
sizey + 2*3), NULL);
1333 if(err != CL_SUCCESS)
goto error;
1339 .cellsize = 4 *
sizeof(float), .overhead = 0,
1340 .sizex = 1 << 8, .sizey = 1 << 8 };
1346 size_t local[3] = { locopt.
sizex, locopt.
sizey, 1 };
1354 sizeof(
float) * 4 * (locopt.
sizex + 2) * (locopt.
sizey + 2), NULL);
1357 if(err != CL_SUCCESS)
goto error;
1365 dev_aux = dev_green_eq = dev_tmp = dev_med = NULL;
1389 const int iterations)
1391 if(iterations <= 0)
return TRUE;
1394 const int devid = pipe->
devid;
1397 const int clip_negatives = 1;
1398 const int keep_signed = 0;
1399 const int dense_mult = 1;
1402 cl_mem LF_even = NULL;
1403 cl_mem LF_odd = NULL;
1405 cl_mem
coeff = NULL;
1407 cl_mem coeff_tmp = NULL;
1408 cl_mem reconstructed_a = NULL;
1409 cl_mem reconstructed_b = NULL;
1410 cl_mem residual = NULL;
1411 cl_mem reconstructed_read = NULL;
1412 cl_mem reconstructed_write = NULL;
1413 cl_mem reconstructed_final = NULL;
1428 for(
int iteration = 0; iteration < iterations; ++iteration)
1430 reconstructed_read = reconstructed_a;
1431 reconstructed_write = reconstructed_b;
1432 reconstructed_final = NULL;
1437 const int mult = 1 << s;
1438 const int first_scale = (s == 0);
1444 buffer_in = dev_out;
1445 buffer_out = LF_odd;
1450 buffer_out = LF_even;
1454 buffer_in = LF_even;
1455 buffer_out = LF_odd;
1460 .yoffset = 0, .yfactor = 1,
1461 .cellsize = 4 *
sizeof(float), .overhead = 0,
1462 .sizex = 1 << 16, .sizey = 1 };
1464 hblocksize = hlocopt.
sizex;
1471 const size_t horizontal_local[3] = { hblocksize, 1, 1 };
1479 (hblocksize + 4 * mult) * 4 *
sizeof(
float), NULL);
1481 horizontal_sizes, horizontal_local);
1493 if(err != CL_SUCCESS)
goto error;
1497 .yoffset = 2 * mult, .yfactor = 1,
1498 .cellsize = 4 *
sizeof(float), .overhead = 0,
1499 .sizex = 1, .sizey = 1 << 16 };
1501 vblocksize = vlocopt.
sizey;
1508 const size_t vertical_local[3] = { 1, vblocksize, 1 };
1516 (vblocksize + 4 * mult) * 4 *
sizeof(
float), NULL);
1518 vertical_sizes, vertical_local);
1530 if(err != CL_SUCCESS)
goto error;
1538 if(err != CL_SUCCESS)
goto error;
1546 if(err != CL_SUCCESS)
goto error;
1555 if(err != CL_SUCCESS)
goto error;
1564 if(err != CL_SUCCESS)
goto error;
1573 if(err != CL_SUCCESS)
goto error;
1582 if(err != CL_SUCCESS)
goto error;
1594 if(err != CL_SUCCESS)
goto error;
1596 residual = buffer_out;
1597 reconstructed_final = reconstructed_write;
1598 cl_mem tmp = reconstructed_read;
1599 reconstructed_read = reconstructed_write;
1600 reconstructed_write = tmp;
1609 if(err != CL_SUCCESS)
goto error;
1636 cl_mem dev_in, cl_mem dev_out)
1640 dt_times_t start_time = { 0 }, end_time = { 0 };
1655 gboolean showmask =
FALSE;
1659 if(
g) showmask = (
g->visual_mask);
1668 "[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",
1669 (
void *)pipe, _pipe_type_string(pipe->
type), (
unsigned long)pthread_self(), (
void *)piece,
1671 piece->
dsc_in.
filters, filters, method2string(demosaicing_method));
1673 cl_mem high_image = NULL;
1674 cl_mem low_image = NULL;
1675 cl_mem blend = NULL;
1676 cl_mem details = NULL;
1677 cl_mem dev_aux = NULL;
1678 cl_mem dev_xtrans = NULL;
1680 const int devid = pipe->
devid;
1681 gboolean retval =
FALSE;
1689 if(!
process_default_cl(self, pipe, piece, dev_in, dev_out, roi_in, roi_out, demosaicing_method))
return FALSE;
1713 if(err != CL_SUCCESS)
goto finish;
1741 if(err != CL_SUCCESS)
goto finish;
1755 if(!
process_rcd_cl(self, pipe, piece, dev_in, high_image, roi_in, roi_in,
FALSE))
goto finish;
1782 dt_print(
DT_DEBUG_OPENCL,
"[opencl_demosaic] demosaicing method '%s' not yet supported by opencl code\n", method2string(demosaicing_method));
1788 const float mpixels = (roi_in->
width * roi_in->
height) / 1.0e6;
1790 const float tclock = end_time.clock - start_time.
clock;
1791 const float uclock = end_time.user - start_time.
user;
1792 fprintf(stderr,
" [demosaic] process GPU `%s' did %.2fmpix, %.4f secs (%.4f CPU), %.2f pix/us\n",
1793 method2string(demosaicing_method & ~
DEMOSAIC_DUAL), mpixels, tclock, uclock, mpixels / tclock);
1831 retval =
dual_demosaic_cl(self, pipe, piece, details, blend, high_image, low_image, dev_aux,
width,
height, showmask);
1837 fprintf(stderr,
" [demosaic] GPU dual blending %.4f secs (%.4f CPU)\n", end_time.clock - start_time.
clock, end_time.user - start_time.
user);
1844 if(err != CL_SUCCESS)
1855 if(!retval && dual)
dt_control_log(_(
"[dual demosaic_cl] internal problem"));
1887 tiling->factor = 1.0f + ioratio;
1888 tiling->factor += fmax(1.0f + greeneq, smooth);
1903 tiling->factor = 1.0f + ioratio;
1904 tiling->factor += ndir * 1.0f
1909 tiling->factor += fmax(1.0f + greeneq, smooth);
1914 tiling->overlap = overlap;
1918 tiling->factor = 1.0f + ioratio;
1919 tiling->factor += fmax(1.0f + greeneq, smooth);
1929 tiling->factor = 1.0f + ioratio;
1930 tiling->factor += fmax(1.0f + greeneq, smooth);
1940 tiling->factor = 1.0f + ioratio;
1941 tiling->factor += fmax(1.0f + greeneq, smooth);
1962 const int program = 0;
1978 const int other = 14;
1991 const int markesteijn = 16;
2025 const int wavelets = 35;
2112 dt_iop_fmt_log(self,
"force_enable: class=%s needs_demosaic=%d current=%d -> %d",
2125 d->green_eq =
p->green_eq;
2126 d->color_smoothing =
p->color_smoothing;
2127 d->median_thrs =
p->median_thrs;
2128 d->dual_thrs =
p->dual_thrs;
2129 d->lmmse_refine =
p->lmmse_refine;
2150 d->median_thrs = 0.0f;
2155 d->color_smoothing = 0;
2156 d->dual_thrs = 0.0f;
2161 d->dual_thrs = 0.0f;
2165 d->color_smoothing = 0;
2167 d->demosaicing_method = use_method;
2170 switch(
d->demosaicing_method)
2236 NULL,
d->CAM_to_RGB,
2240 fprintf(stderr,
"[colorspaces] `%s' color matrix not found for 4bayer image!\n", camera);
2241 dt_control_log(_(
"`%s' color matrix not found for 4bayer image!"), camera);
2245 dt_iop_fmt_log(self,
"commit: class=%s in(filters=%u ch=%i) method=%d passthrough=%d -> enabled=%d cl_ready=%d",
2274 module->hide_enable_button = 1;
2278 module->default_enabled = dt_image_needs_demosaic(&module->dev->image_storage);
2279 dt_iop_fmt_log(module,
"reload_defaults: class=%s needs_demosaic=%d filters=%u mono=%d method=%d -> default_enabled=%d",
2306 const gboolean isdual = !isdownsample && (use_method &
DEMOSAIC_DUAL);
2313 gtk_widget_set_visible(
g->demosaic_method_bayer, bayer);
2314 gtk_widget_set_visible(
g->demosaic_method_xtrans, !bayer);
2320 gtk_widget_set_visible(
g->median_thrs, bayer && isppg);
2321 gtk_widget_set_visible(
g->greeneq, !passing && !isdownsample);
2322 gtk_widget_set_visible(
g->color_smoothing, !passing && !isdual);
2323 gtk_widget_set_visible(
g->dual_thrs, isdual);
2324 gtk_widget_set_visible(
g->lmmse_refine, islmmse);
2331 img->
flags &= ~DT_IMAGE_MONOCHROME_BAYER;
2342 gtk_stack_set_visible_child_name(GTK_STACK(self->
widget), self->
default_enabled ?
"raw" :
"non_raw");
2360 const gboolean was_dualmask =
g->visual_mask;
2375 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."));
2379 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."));
2383 gtk_widget_set_tooltip_text(
g->median_thrs, _(
"threshold for edge-aware median.\nset to 0.0 to switch off\n"
2384 "set to 1.0 to ignore edges"));
2388 gtk_widget_set_tooltip_text(
g->dual_thrs, _(
"contrast threshold for dual demosaic.\nset to 0.0 for high frequency content\n"
2389 "set to 1.0 for flat content\ntoggle to visualize the mask"));
2393 g_signal_connect(G_OBJECT(
g->dual_thrs),
"quad-pressed", G_CALLBACK(
_visualize_callback), self);
2396 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"));
2399 gtk_widget_set_tooltip_text(
g->color_smoothing, _(
"how many post-demosaic smoothing passes.\nin downsample mode this sets the guided detail equalization iterations"));
2402 gtk_widget_set_tooltip_text(
g->greeneq, _(
"green channels matching method"));
2405 self->
widget = gtk_stack_new();
2406 gtk_stack_set_homogeneous(GTK_STACK(self->
widget),
FALSE);
2409 gtk_widget_set_tooltip_text(label_non_raw, _(
"demosaicing is only used for color raw images"));
2411 gtk_stack_add_named(GTK_STACK(self->
widget), label_non_raw,
"non_raw");
2412 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...
void void void gboolean dt_gui_widgets_suppressed(void)
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)
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_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])
@ DT_DEV_PIXELPIPE_THUMBNAIL
@ DT_DEV_PIXELPIPE_EXPORT
@ DT_DEV_PIXELPIPE_PREVIEW
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_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)