Skip to content

Commit

Permalink
Adding developers demosaic algo showing photosite values
Browse files Browse the repository at this point in the history
While working on fixing chromatic aberration issues i needed a dt-internal way to
find out the raw values from the photosites represented as rgb colors.
No opencl implementation done as this is not intended for user photo developing but
for analysing color details so not performance critical.
  • Loading branch information
jenshannoschwalm authored and aurelienpierre committed Aug 14, 2020
1 parent 4b3b27c commit 926b45b
Showing 1 changed file with 108 additions and 11 deletions.
119 changes: 108 additions & 11 deletions src/iop/demosaic.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,12 +56,15 @@ typedef enum dt_iop_demosaic_method_t
DT_IOP_DEMOSAIC_AMAZE = 1, // $DESCRIPTION: "AMaZE (slow)"
DT_IOP_DEMOSAIC_VNG4 = 2, // $DESCRIPTION: "VNG4"
DT_IOP_DEMOSAIC_PASSTHROUGH_MONOCHROME = 3, // $DESCRIPTION: "passthrough (monochrome) (experimental)"
DT_IOP_DEMOSAIC_PASSTHROUGH_COLOR = 4, // $DESCRIPTION: "photosite color"
// methods for x-trans images
DT_IOP_DEMOSAIC_VNG = DEMOSAIC_XTRANS | 0, // $DESCRIPTION: "VNG"
DT_IOP_DEMOSAIC_MARKESTEIJN = DEMOSAIC_XTRANS | 1, // $DESCRIPTION: "Markesteijn 1-pass"
DT_IOP_DEMOSAIC_MARKESTEIJN_3 = DEMOSAIC_XTRANS | 2, // $DESCRIPTION: "Markesteijn 3-pass (slow)"
DT_IOP_DEMOSAIC_PASSTHR_MONOX = DEMOSAIC_XTRANS | 3, // $DESCRIPTION: "passthrough (monochrome) (experimental)"
DT_IOP_DEMOSAIC_FDC = DEMOSAIC_XTRANS | 4 // $DESCRIPTION: "frequency domain chroma (slow)"
DT_IOP_DEMOSAIC_FDC = DEMOSAIC_XTRANS | 4, // $DESCRIPTION: "frequency domain chroma (slow)"
DT_IOP_DEMOSAIC_PASSTHR_COLORX = DEMOSAIC_XTRANS | 5 // $DESCRIPTION: "photosite color"

} dt_iop_demosaic_method_t;

typedef enum dt_iop_demosaic_greeneq_t
Expand Down Expand Up @@ -251,6 +254,9 @@ static const char* method2string(dt_iop_demosaic_method_t method)
case DT_IOP_DEMOSAIC_PASSTHROUGH_MONOCHROME:
string = "passthrough monochrome";
break;
case DT_IOP_DEMOSAIC_PASSTHROUGH_COLOR:
string = "photosites";
break;
case DT_IOP_DEMOSAIC_VNG:
string = "VNG (xtrans)";
break;
Expand All @@ -263,6 +269,12 @@ static const char* method2string(dt_iop_demosaic_method_t method)
case DT_IOP_DEMOSAIC_FDC:
string = "Frequency Domain Chroma (xtrans)";
break;
case DT_IOP_DEMOSAIC_PASSTHR_MONOX:
string = "passthrough monochrome (xtrans)";
break;
case DT_IOP_DEMOSAIC_PASSTHR_COLORX:
string = "photosites (xtrans)";
break;
default:
string = "(unknown method)";
}
Expand Down Expand Up @@ -2431,6 +2443,61 @@ static void passthrough_monochrome(float *out, const float *const in, dt_iop_roi
}
}

static 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])
{
assert(roi_in->width >= roi_out->width);
assert(roi_in->height >= roi_out->height);


if(filters != 9u)
{
#ifdef _OPENMP
#pragma omp parallel for default(none) \
dt_omp_firstprivate(in, roi_out, roi_in, filters) \
shared(out) \
schedule(static) \
collapse(2)
#endif

for(int row = 0; row < (roi_out->height); row++)
{
for(int col = 0; col < (roi_out->width); col++)
{
const float val = in[col + roi_out->x + ((row + roi_out->y) * roi_in->width)];
const uint32_t offset = (size_t)4 * ((size_t)row * roi_out->width + col);
const uint32_t ch = FC(row + roi_out->y, col + roi_out->x, filters);

out[offset] = out[offset + 1] = out[offset + 2] = 0.0f;
out[offset + ch] = val;
}
}
}
else
{
#ifdef _OPENMP
#pragma omp parallel for default(none) \
dt_omp_firstprivate(in, roi_out, roi_in, xtrans) \
shared(out) \
schedule(static) \
collapse(2)
#endif

for(int row = 0; row < (roi_out->height); row++)
{
for(int col = 0; col < (roi_out->width); col++)
{
const float val = in[col + roi_out->x + ((row + roi_out->y) * roi_in->width)];
const uint32_t offset = (size_t)4 * ((size_t)row * roi_out->width + col);
const uint32_t ch = FCxtrans(row, col, roi_in, xtrans);

out[offset] = out[offset + 1] = out[offset + 2] = 0.0f;
out[offset + ch] = val;
}
}
}
}

/** 1:1 demosaic from in to out, in is full buf, out is translated/cropped (scale == 1.0!) */
static void 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)
Expand Down Expand Up @@ -2826,8 +2893,9 @@ void process(struct dt_iop_module_t *self, dt_dev_pixelpipe_iop_t *piece, const
const int qual_flags = demosaic_qual_flags(piece, img, roi_out);
int demosaicing_method = data->demosaicing_method;
if((qual_flags & DEMOSAIC_MEDIUM_QUAL)
&& // only overwrite setting if quality << requested and in dr mode
(demosaicing_method != DT_IOP_DEMOSAIC_PASSTHROUGH_MONOCHROME)) // do not touch this special method
// only overwrite setting if quality << requested and in dr mode and not a special method
&& (demosaicing_method != DT_IOP_DEMOSAIC_PASSTHROUGH_MONOCHROME)
&& (demosaicing_method != DT_IOP_DEMOSAIC_PASSTHROUGH_COLOR))
demosaicing_method = (piece->pipe->dsc.filters != 9u) ? DT_IOP_DEMOSAIC_PPG : DT_IOP_DEMOSAIC_MARKESTEIJN;

const float *const pixels = (float *)i;
Expand All @@ -2852,6 +2920,10 @@ void process(struct dt_iop_module_t *self, dt_dev_pixelpipe_iop_t *piece, const
{
passthrough_monochrome(tmp, pixels, &roo, &roi);
}
else if(demosaicing_method == DT_IOP_DEMOSAIC_PASSTHROUGH_COLOR)
{
passthrough_color(tmp, pixels, &roo, &roi, piece->pipe->dsc.filters, xtrans);
}
else if(piece->pipe->dsc.filters == 9u)
{
if(demosaicing_method == DT_IOP_DEMOSAIC_FDC && (qual_flags & DEMOSAIC_XTRANS_FULL))
Expand Down Expand Up @@ -2920,6 +2992,8 @@ void process(struct dt_iop_module_t *self, dt_dev_pixelpipe_iop_t *piece, const
{
if(demosaicing_method == DT_IOP_DEMOSAIC_PASSTHROUGH_MONOCHROME)
dt_iop_clip_and_zoom_demosaic_passthrough_monochrome_f((float *)o, pixels, &roo, &roi, roo.width, roi.width);
else if(demosaicing_method == DT_IOP_DEMOSAIC_PASSTHROUGH_COLOR)
dt_iop_clip_and_zoom_demosaic_passthrough_monochrome_f((float *)o, pixels, &roo, &roi, roo.width, roi.width);
else // sample half-size raw (Bayer) or 1/3-size raw (X-Trans)
if(piece->pipe->dsc.filters == 9u)
dt_iop_clip_and_zoom_demosaic_third_size_xtrans_f((float *)o, pixels, &roo, &roi, roo.width, roi.width,
Expand Down Expand Up @@ -4624,9 +4698,10 @@ void tiling_callback(struct dt_iop_module_t *self, struct dt_dev_pixelpipe_iop_t

if((demosaicing_method == DT_IOP_DEMOSAIC_PPG) ||
(demosaicing_method == DT_IOP_DEMOSAIC_PASSTHROUGH_MONOCHROME) ||
(demosaicing_method == DT_IOP_DEMOSAIC_PASSTHROUGH_COLOR) ||
(demosaicing_method == DT_IOP_DEMOSAIC_AMAZE))
{
// Bayer pattern with PPG, Monochrome and Amaze
// Bayer pattern with PPG, Passthrough or Amaze
tiling->factor = 1.0f + ioratio; // in + out

if(full_scale_demosaicing && unscaled)
Expand Down Expand Up @@ -4797,14 +4872,23 @@ void commit_params(struct dt_iop_module_t *self, dt_iop_params_t *params, dt_dev
d->demosaicing_method = p->demosaicing_method;

if(p->demosaicing_method == DT_IOP_DEMOSAIC_PASSTHROUGH_MONOCHROME
|| p->demosaicing_method == (DEMOSAIC_XTRANS | DT_IOP_DEMOSAIC_PASSTHROUGH_MONOCHROME))
|| p->demosaicing_method == DT_IOP_DEMOSAIC_PASSTHR_MONOX)
{
d->demosaicing_method = DT_IOP_DEMOSAIC_PASSTHROUGH_MONOCHROME;
d->green_eq = DT_IOP_GREEN_EQ_NO;
d->color_smoothing = 0;
d->median_thrs = 0.0f;
}

if(p->demosaicing_method == DT_IOP_DEMOSAIC_PASSTHROUGH_COLOR
|| p->demosaicing_method == DT_IOP_DEMOSAIC_PASSTHR_COLORX)
{
d->demosaicing_method = DT_IOP_DEMOSAIC_PASSTHROUGH_COLOR;
d->green_eq = DT_IOP_GREEN_EQ_NO;
d->color_smoothing = 0;
d->median_thrs = 0.0f;
}

if(d->demosaicing_method == DT_IOP_DEMOSAIC_AMAZE)
{
d->median_thrs = 0.0f;
Expand All @@ -4825,6 +4909,9 @@ void commit_params(struct dt_iop_module_t *self, dt_iop_params_t *params, dt_dev
case DT_IOP_DEMOSAIC_PASSTHROUGH_MONOCHROME:
piece->process_cl_ready = 1;
break;
case DT_IOP_DEMOSAIC_PASSTHROUGH_COLOR:
piece->process_cl_ready = 0;
break;
case DT_IOP_DEMOSAIC_VNG:
piece->process_cl_ready = 1;
break;
Expand Down Expand Up @@ -4893,13 +4980,16 @@ void gui_update(struct dt_iop_module_t *self)
dt_bauhaus_combobox_set_from_value(g->demosaic_method_xtrans, p->demosaicing_method);
}

if(p->demosaicing_method == DT_IOP_DEMOSAIC_PASSTHROUGH_MONOCHROME)
if((p->demosaicing_method == DT_IOP_DEMOSAIC_PASSTHROUGH_MONOCHROME) ||
(p->demosaicing_method == DT_IOP_DEMOSAIC_PASSTHROUGH_COLOR) ||
(p->demosaicing_method == DT_IOP_DEMOSAIC_PASSTHR_MONOX) ||
(p->demosaicing_method == DT_IOP_DEMOSAIC_PASSTHR_COLORX))
{
gtk_widget_hide(g->median_thrs);
gtk_widget_hide(g->color_smoothing);
gtk_widget_hide(g->greeneq);
}

if(p->demosaicing_method == DT_IOP_DEMOSAIC_AMAZE || p->demosaicing_method == DT_IOP_DEMOSAIC_VNG4)
{
gtk_widget_hide(g->median_thrs);
Expand Down Expand Up @@ -4952,12 +5042,19 @@ void gui_changed(dt_iop_module_t *self, GtkWidget *w, void *previous)
dt_iop_demosaic_gui_data_t *g = (dt_iop_demosaic_gui_data_t *)self->gui_data;
dt_iop_demosaic_params_t *p = (dt_iop_demosaic_params_t *)self->params;

const gboolean extras =
(p->demosaicing_method != DT_IOP_DEMOSAIC_PASSTHROUGH_MONOCHROME) &&
(p->demosaicing_method != DT_IOP_DEMOSAIC_PASSTHROUGH_COLOR) &&
(p->demosaicing_method != DT_IOP_DEMOSAIC_PASSTHR_MONOX) &&
(p->demosaicing_method != DT_IOP_DEMOSAIC_PASSTHR_COLORX);

if(w == g->demosaic_method_bayer)
{
gtk_widget_set_visible(g->median_thrs, p->demosaicing_method == DT_IOP_DEMOSAIC_PPG);
gtk_widget_set_visible(g->color_smoothing, p->demosaicing_method != DT_IOP_DEMOSAIC_PASSTHROUGH_MONOCHROME);
gtk_widget_set_visible(g->greeneq, p->demosaicing_method != DT_IOP_DEMOSAIC_PASSTHROUGH_MONOCHROME);
}

gtk_widget_set_visible(g->color_smoothing, extras);
gtk_widget_set_visible(g->greeneq, extras);
}

void gui_init(struct dt_iop_module_t *self)
Expand All @@ -4968,11 +5065,11 @@ void gui_init(struct dt_iop_module_t *self)
g->box_raw = self->widget = gtk_box_new(GTK_ORIENTATION_VERTICAL, DT_BAUHAUS_SPACE);

g->demosaic_method_bayer = dt_bauhaus_combobox_from_params(self, "demosaicing_method");
for(int i=0;i<5;i++) dt_bauhaus_combobox_remove_at(g->demosaic_method_bayer, 4);
for(int i=0;i<6;i++) dt_bauhaus_combobox_remove_at(g->demosaic_method_bayer, 5);
gtk_widget_set_tooltip_text(g->demosaic_method_bayer, _("demosaicing raw data method"));

g->demosaic_method_xtrans = dt_bauhaus_combobox_from_params(self, "demosaicing_method");
for(int i=0;i<4;i++) dt_bauhaus_combobox_remove_at(g->demosaic_method_xtrans, 0);
for(int i=0;i<5;i++) dt_bauhaus_combobox_remove_at(g->demosaic_method_xtrans, 0);
gtk_widget_set_tooltip_text(g->demosaic_method_xtrans, _("demosaicing raw data method"));

g->median_thrs = dt_bauhaus_slider_from_params(self, "median_thrs");
Expand Down

0 comments on commit 926b45b

Please sign in to comment.