118 return C_(
"modulename",
"Raw settings");
145 void *new_params,
const int new_version)
148 typedef struct dt_iop_rawprepare_params_v1_t
154 uint16_t raw_black_level_separate[4];
155 uint16_t raw_white_point;
156 } dt_iop_rawprepare_params_v1_t;
158 if(old_version == 1 && new_version == 2)
160 dt_iop_rawprepare_params_v1_t *o = (dt_iop_rawprepare_params_v1_t *)old_params;
161 dt_iop_rawprepare_params_v2_t *
n = (dt_iop_rawprepare_params_v2_t *)new_params;
162 memcpy(
n, o,
sizeof *o);
173 "touch with great care!"),
175 _(
"linear, raw, scene-referred"),
177 _(
"linear, raw, scene-referred"));
189 .raw_black_level_separate[0] = 0,
190 .raw_black_level_separate[1] = 0,
191 .raw_black_level_separate[2] = 0,
192 .raw_black_level_separate[3] = 0,
193 .raw_white_point = UINT16_MAX },
201 const double scale = roi_in->
scale;
202 return (
int)roundf((
double)
value * scale);
224 const uint32_t crop_x = compute_proper_crop(piece, roi_in,
d->
x + roi_in->
x);
225 const uint32_t crop_y = compute_proper_crop(piece, roi_in,
d->
y + roi_in->
y);
239 for(
int i = 0;
i < 6; ++
i)
241 for(
int j = 0; j < 6; ++j)
251 float *
const restrict points,
size_t points_count)
258 if (
d->x == 0 &&
d->y == 0)
return 1;
261 const double x = (
double)
d->x * scale;
262 const double y = (
double)
d->y * scale;
264 for(
size_t i = 0;
i < points_count * 2;
i += 2)
275 float *
const restrict points,
size_t points_count)
282 if (
d->x == 0 &&
d->y == 0)
return 1;
285 const double x = (
double)
d->x * scale;
286 const double y = (
double)
d->y * scale;
288 for(
size_t i = 0;
i < points_count * 2;
i += 2)
317 roi_out->
x = roi_out->
y = 0;
319 const double x =
d->x +
d->width;
320 const double y =
d->y +
d->height;
321 const double scale = roi_in->
scale;
322 roi_out->
width = (int)round((
double)roi_out->
width -
x * scale);
323 roi_out->
height = (int)round((
double)roi_out->
height - y * scale);
339 const double x =
d->x +
d->width;
340 const double y =
d->y +
d->height;
341 const double scale = roi_in->
scale;
342 roi_in->
width = (int)round((
double)roi_in->
width +
x * scale);
343 roi_in->
height = (int)round((
double)roi_in->
height + y * scale);
366 const int row,
const int col,
367 const int32_t
x,
const int32_t y)
369 return ((((
row + roi_out->
y + y) & 1) << 1) + ((col + roi_out->
x +
x) & 1));
390 const int csx = compute_proper_crop(piece, roi_in,
p->
x);
391 const int csy = compute_proper_crop(piece, roi_in,
p->
y);
395 const uint16_t *
const restrict in = (
const uint16_t *
const restrict)input;
397 int max_RGB[4] = { 0 };
401 for(
int j = 0; j < roi_out->
width; j++)
403 const size_t channel = BL(roi_out,
i, j,
p->
x,
p->y);
404 const size_t pin = roi_in->
width * (
i + csy) + j + csx;
405 const int pixel = in[pin];
406 max_RGB[channel] =
MAX(max_RGB[channel], pixel);
420 const void *
const ivoid,
void *
const ovoid)
427 const int input_width = roi_in->
width;
428 const int roi_x = roi_out->
x;
429 const int roi_y = roi_out->
y;
430 const int cfa_x = roi_x +
d->x;
431 const int cfa_y = roi_y +
d->y;
435 const int csx = compute_proper_crop(piece, roi_in,
d->
x);
436 const int csy = compute_proper_crop(piece, roi_in,
d->
y);
442 const uint16_t *
const in = (
const uint16_t *
const)ivoid;
443 float *
const out = (
float *
const)
ovoid;
444 const int x_phase = cfa_x & 1;
446 for(
int k = 0;
k < 4;
k++) inv_div[
k] = 1.0f /
d->div[
k];
448 for(
int j = 0; j <
height; j++)
452 const size_t pin = (size_t)input_width * (j + csy) + csx;
453 const size_t pout = (size_t)j *
width;
454 const int row_phase = ((j + cfa_y) & 1) << 1;
455 const int id0 = row_phase + x_phase;
456 const int id1 = row_phase + (x_phase ^ 1);
457 const float sub0 =
d->sub[id0];
458 const float sub1 =
d->sub[id1];
459 const float inv0 = inv_div[id0];
460 const float inv1 = inv_div[id1];
465 out[pout +
i + 0] = ((float)in[pin +
i + 0] - sub0) * inv0;
466 out[pout +
i + 1] = ((float)in[pin +
i + 1] - sub1) * inv1;
471 const int id = row_phase + ((x_phase +
i) & 1);
472 out[pout +
i] = ((float)in[pin +
i] -
d->sub[
id]) * inv_div[id];
481 const float *
const in = (
const float *
const)ivoid;
482 float *
const out = (
float *
const)
ovoid;
483 const int x_phase = cfa_x & 1;
485 for(
int k = 0;
k < 4;
k++) inv_div[
k] = 1.0f /
d->div[
k];
488 for(
int j = 0; j <
height; j++)
492 const size_t pin = (size_t)input_width * (j + csy) + csx;
493 const size_t pout = (size_t)j *
width;
494 const int row_phase = ((j + cfa_y) & 1) << 1;
495 const int id0 = row_phase + x_phase;
496 const int id1 = row_phase + (x_phase ^ 1);
497 const float sub0 =
d->sub[id0];
498 const float sub1 =
d->sub[id1];
499 const float inv0 = inv_div[id0];
500 const float inv1 = inv_div[id1];
505 out[pout +
i + 0] = (in[pin +
i + 0] - sub0) * inv0;
506 out[pout +
i + 1] = (in[pin +
i + 1] - sub1) * inv1;
511 const int id = row_phase + ((x_phase +
i) & 1);
512 out[pout +
i] = (in[pin +
i] -
d->sub[id]) * inv_div[
id];
520 const float *
const in = (
const float *
const)ivoid;
521 float *
const out = (
float *
const)
ovoid;
523 const float sub =
d->sub[0];
524 const float div =
d->div[0];
528 for(
int j = 0; j <
height; j++)
532 for(
int c = 0; c <
ch; c++)
534 const size_t pin = (size_t)
ch * (input_width * (j + csy) + csx +
i) + c;
535 const size_t pout = (size_t)
ch * (j *
width +
i) + c;
537 out[pout] = (in[pin] - sub) / div;
546 const uint32_t map_w =
d->gainmaps[0]->map_points_h;
547 const uint32_t map_h =
d->gainmaps[0]->map_points_v;
548 const float im_to_rel_x = 1.0f / piece->
buf_in.
width;
550 const float rel_to_map_x = 1.0f /
d->gainmaps[0]->map_spacing_h;
551 const float rel_to_map_y = 1.0f /
d->gainmaps[0]->map_spacing_v;
552 const float map_origin_h =
d->gainmaps[0]->map_origin_h;
553 const float map_origin_v =
d->gainmaps[0]->map_origin_v;
554 float *
const out = (
float *
const)
ovoid;
556 for(
int j = 0; j <
height; j++)
558 const float y_map = CLAMP(((roi_y + csy + j) * im_to_rel_y - map_origin_v) * rel_to_map_y, 0, map_h);
559 const uint32_t y_i0 =
MIN(y_map, map_h - 1);
560 const uint32_t y_i1 =
MIN(y_i0 + 1, map_h - 1);
561 const float y_frac = y_map - y_i0;
562 const float * restrict map_row0[4];
563 const float * restrict map_row1[4];
564 for(
int f = 0;
f < 4;
f++)
566 map_row0[
f] = &
d->gainmaps[
f]->map_gain[y_i0 * map_w];
567 map_row1[
f] = &
d->gainmaps[
f]->map_gain[y_i1 * map_w];
571 const int id = BL(roi_out, j,
i,
d->
x,
d->y);
572 const float x_map = CLAMP(((roi_x + csx +
i) * im_to_rel_x - map_origin_h) * rel_to_map_x, 0, map_w);
573 const uint32_t x_i0 =
MIN(x_map, map_w - 1);
574 const uint32_t x_i1 =
MIN(x_i0 + 1, map_w - 1);
575 const float x_frac = x_map - x_i0;
576 const float gain_top = (1.0f - x_frac) * map_row0[
id][x_i0] + x_frac * map_row0[
id][x_i1];
577 const float gain_bottom = (1.0f - x_frac) * map_row1[
id][x_i0] + x_frac * map_row1[
id][x_i1];
578 out[j *
width +
i] *= (1.0f - y_frac) * gain_top + y_frac * gain_bottom;
589 cl_mem dev_in, cl_mem dev_out)
599 const int devid = pipe->
devid;
600 cl_mem dev_sub = NULL;
601 cl_mem dev_div = NULL;
602 cl_mem dev_gainmap[4] = {0};
606 gboolean gainmap_args =
FALSE;
611 if(
d->apply_gainmaps)
623 if(
d->apply_gainmaps)
638 const int csx = compute_proper_crop(piece, roi_in,
d->
x), csy = compute_proper_crop(piece, roi_in,
d->
y);
662 const int map_size[2] = {
d->gainmaps[0]->map_points_h,
d->gainmaps[0]->map_points_v };
664 const float rel_to_map[2] = { 1.0 /
d->gainmaps[0]->map_spacing_h, 1.0 /
d->gainmaps[0]->map_spacing_v };
665 const float map_origin[2] = {
d->gainmaps[0]->map_origin_h,
d->gainmaps[0]->map_origin_v };
667 for(
int i = 0;
i < 4;
i++)
670 if(dev_gainmap[
i] == NULL)
goto error;
672 map_size[0], map_size[1],
sizeof(
float));
673 if(err != CL_SUCCESS)
goto error;
686 if(err != CL_SUCCESS)
goto error;
724 if(imgid <= 0)
return FALSE;
733 if(test)
return FALSE;
753 for(
int i = 0;
i < 4;
i++)
759 g->plane != 0 ||
g->planes != 1 ||
g->map_planes != 1 ||
760 g->row_pitch != 2 ||
g->col_pitch != 2 ||
761 g->map_points_v < 2 ||
g->map_points_h < 2 ||
762 g->top > 1 ||
g->left > 1 ||
765 uint32_t filter = ((
g->top & 1) << 1) + (
g->left & 1);
766 gainmaps[filter] =
g;
770 if(gainmaps[0] == NULL || gainmaps[1] == NULL || gainmaps[2] == NULL || gainmaps[3] == NULL)
774 for(
int i = 1;
i < 4;
i++)
776 if(gainmaps[
i]->map_points_h != gainmaps[0]->map_points_h ||
777 gainmaps[
i]->map_points_v != gainmaps[0]->map_points_v ||
778 gainmaps[
i]->map_spacing_h != gainmaps[0]->map_spacing_h ||
779 gainmaps[
i]->map_spacing_v != gainmaps[0]->map_spacing_v ||
780 gainmaps[
i]->map_origin_h != gainmaps[0]->map_origin_h ||
781 gainmaps[
i]->map_origin_v != gainmaps[0]->map_origin_v)
786 memcpy(gainmaps_out, gainmaps,
sizeof(gainmaps));
801 d->height =
p->height;
805 const float white = (float)
p->raw_white_point;
807 for(
int i = 0;
i < 4;
i++)
809 d->sub[
i] = (float)
p->raw_black_level_separate[
i];
810 d->div[
i] = (white -
d->sub[
i]);
815 const float normalizer
817 const float white = (float)
p->raw_white_point / normalizer;
819 for(
int i = 0;
i < 4;
i++)
821 black +=
p->raw_black_level_separate[
i] / normalizer;
825 for(
int i = 0;
i < 4;
i++)
828 d->div[
i] = (white - black);
833 for(uint8_t
i = 0;
i < 4;
i++)
835 black += (float)
p->raw_black_level_separate[
i];
837 d->rawprepare.raw_black_level = (uint16_t)(black / 4.0f);
838 d->rawprepare.raw_white_point =
p->raw_white_point;
846 d->apply_gainmaps =
FALSE;
858 dt_iop_fmt_log(self,
"commit: class=%s needs_rawprepare=%d normalized=%d cl_ok=%d -> enabled=%d",
889 const gboolean
state = active && current_state;
890 dt_iop_fmt_log(self,
"force_enable: class=%s supported=%d current=%d -> %d",
892 active, current_state,
state);
921 gtk_stack_set_visible_child_name(GTK_STACK(self->
widget), self->
default_enabled ?
"raw" :
"non_raw");
926 const int program = 2;
956 for(
int i = 0;
i < 4;
i++)
957 av +=
p->raw_black_level_separate[
i];
959 for(
int i = 0;
i < 4;
i++)
964 for(
int i = 1;
i < 4;
i++)
965 gtk_widget_set_visible(
g->black_level_separate[
i], !is_monochrome);
979 if(w ==
g->black_level_separate[0])
981 const int val =
p->raw_black_level_separate[0];
982 for(
int i = 1;
i < 4;
i++)
989 = { N_(
"black level 0"),
992 N_(
"black level 3") };
1000 for(
int i = 0;
i < 4;
i++)
1002 gchar *par = g_strdup_printf(
"raw_black_level_separate[%i]",
i);
1006 gtk_widget_set_tooltip_text(
g->black_level_separate[
i], _(
black_label[
i]));
1013 gtk_widget_set_tooltip_text(
g->white_point, _(
"white point"));
1017 gtk_widget_set_tooltip_text(
g->flat_field, _(
"flat field correction to compensate for lens shading"));
1019 gtk_box_pack_start(GTK_BOX(self->
widget),
1023 gtk_widget_set_tooltip_text(
g->x, _(
"crop from left border"));
1027 gtk_widget_set_tooltip_text(
g->y, _(
"crop from top"));
1031 gtk_widget_set_tooltip_text(
g->width, _(
"crop from right border"));
1035 gtk_widget_set_tooltip_text(
g->height, _(
"crop from bottom"));
1039 self->
widget = gtk_stack_new();
1040 gtk_stack_set_homogeneous(GTK_STACK(self->
widget),
FALSE);
1042 GtkWidget *label_non_raw =
dt_ui_label_new(_(
"raw black/white point correction\nonly works for the sensors that need it."));
1044 gtk_stack_add_named(GTK_STACK(self->
widget), label_non_raw,
"non_raw");
1045 gtk_stack_add_named(GTK_STACK(self->
widget), box_raw,
"raw");
static void error(char *msg)
void dt_bauhaus_slider_set_soft_max(GtkWidget *widget, float val)
void dt_bauhaus_slider_set(GtkWidget *widget, float pos)
void dt_bauhaus_combobox_set(GtkWidget *widget, const int pos)
void dt_bauhaus_widget_set_label(GtkWidget *widget, const char *label)
static const dt_aligned_pixel_simd_t const dt_adaptation_t const float p
const dt_aligned_pixel_t f
const dt_colormatrix_t dt_aligned_pixel_t out
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_hdr(const dt_image_t *img)
void dt_image_print_debug_info(const dt_image_t *img, const char *context)
gboolean dt_image_needs_rawprepare(const dt_image_t *img)
void dt_print(dt_debug_thread_t thread, const char *msg,...)
#define dt_free_align(ptr)
static void * dt_calloc_align(size_t size)
float dt_aligned_pixel_simd_t __attribute__((vector_size(16), aligned(16)))
Enable aggressive floating-point arithmetic optimizations, in denormals handling. Set through user pr...
#define DT_MODULE_INTROSPECTION(MODVER, PARAMSTYPE)
#define __DT_CLONE_TARGETS__
#define __OMP_PARALLEL_FOR__(...)
static const dt_aligned_pixel_simd_t value
#define __OMP_PARALLEL_FOR_SIMD__(...)
#define IS_NULL_PTR(p)
C is way too permissive with !=, == and if(var) checks, which can mean too many things depending on w...
#define dt_database_start_transaction(db)
#define dt_database_release_transaction(db)
static GtkWidget * dt_ui_section_label_new(const gchar *str)
#define DT_GUI_BOX_SPACING
static GtkWidget * dt_ui_label_new(const gchar *str)
void dt_gui_presets_add_generic(const char *name, dt_dev_operation_t op, const int32_t version, const void *params, const int32_t params_size, const int32_t enabled, const dt_develop_blend_colorspace_t blend_cst)
@ DT_IMAGE_MONOCHROME_BAYER
void dt_image_cache_read_release(dt_image_cache_t *cache, const dt_image_t *img)
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)
void dt_iop_copy_image_roi(float *const __restrict__ out, const float *const __restrict__ in, const size_t ch, const dt_iop_roi_t *const __restrict__ roi_in, const dt_iop_roi_t *const __restrict__ roi_out, const int zero_pad)
uint32_t dt_rawspeed_crop_dcraw_filters(uint32_t filters, uint32_t crop_x, uint32_t crop_y)
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)...
@ IOP_FLAGS_TILING_FULL_ROI
#define IOP_GUI_ALLOC(module)
GtkWidget * dt_bauhaus_slider_from_params(dt_iop_module_t *self, const char *param)
GtkWidget * dt_bauhaus_combobox_from_params(dt_iop_module_t *self, const char *param)
static float kernel(const float *x, const float *y)
float *const restrict const size_t k
float *const restrict const size_t const size_t ch
int dt_opencl_enqueue_kernel_2d(const int dev, const int kernel, const size_t *sizes)
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)
void dt_opencl_release_mem_object(cl_mem mem)
int dt_opencl_write_host_to_device(const int devid, void *host, void *device, const int width, const int height, const int bpp)
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)
const char ** description(struct dt_iop_module_t *self)
void modify_roi_out(dt_iop_module_t *self, const dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece, dt_iop_roi_t *roi_out, const dt_iop_roi_t *const roi_in)
int distort_backtransform(dt_iop_module_t *self, const dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece, float *const restrict points, size_t points_count)
__DT_CLONE_TARGETS__ int process(struct dt_iop_module_t *self, const dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece, const void *const ivoid, void *const ovoid)
int distort_transform(dt_iop_module_t *self, const dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece, float *const restrict points, size_t points_count)
void gui_update(dt_iop_module_t *self)
Refresh GUI controls from current params and configuration.
dt_iop_rawprepare_flat_field_t
void modify_roi_in(dt_iop_module_t *self, const dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece, const dt_iop_roi_t *const roi_out, dt_iop_roi_t *roi_in)
static gboolean enable(const dt_image_t *image)
int process_cl(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 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 cleanup_global(dt_iop_module_so_t *self)
void gui_init(dt_iop_module_t *self)
void gui_changed(dt_iop_module_t *self, GtkWidget *w, void *previous)
void reload_defaults(dt_iop_module_t *self)
void cleanup_pipe(dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
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)
void autoset(struct dt_iop_module_t *self, const struct dt_dev_pixelpipe_t *pipe, const struct dt_dev_pixelpipe_iop_t *piece, const void *input)
RawSpeed tends to under-evaluate the white point of RAW images, which leads to RGB values > 1 after n...
void init_presets(dt_iop_module_so_t *self)
gboolean check_gain_maps(dt_iop_module_t *self, dt_dng_gain_map_t **gainmaps_out)
void commit_params(dt_iop_module_t *self, dt_iop_params_t *params, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
gboolean force_enable(struct dt_iop_module_t *self, const gboolean current_state)
void init_pipe(dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
static void _update_output_cfa_descriptor(const dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece, const dt_iop_roi_t *const roi_in, dt_iop_buffer_dsc_t *dsc)
static gboolean image_set_rawcrops(const int32_t imgid, int dx, int dy)
static int image_is_normalized(const dt_image_t *const image)
const gchar * black_label[]
void init_global(dt_iop_module_so_t *self)
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_DEBUG_CONTROL_SIGNAL_RAISE(ctlsig, signal,...)
@ DT_SIGNAL_METADATA_UPDATE
struct _GtkWidget GtkWidget
const float uint32_t state[4]
const struct dt_database_t * db
struct dt_control_signal_t * signals
struct dt_image_cache_t * image_cache
dt_iop_buffer_dsc_t dsc_out
dt_iop_buffer_dsc_t dsc_in
struct dt_iop_module_t *void * data
struct dt_develop_t * dev
uint16_t raw_black_level_separate[4]
struct dt_iop_buffer_dsc_t::@29 rawprepare
dt_iop_buffer_type_t datatype
dt_aligned_pixel_t processed_maximum
GModule *dt_dev_operation_t op
dt_iop_global_data_t * data
int32_t hide_enable_button
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
struct dt_iop_rawprepare_data_t::@59 rawprepare
dt_dng_gain_map_t * gainmaps[4]
int kernel_rawprepare_1f_gainmap
int kernel_rawprepare_1f_unnormalized
int kernel_rawprepare_1f_unnormalized_gainmap
GtkWidget * black_level_separate[4]
uint16_t raw_black_level_separate[4]
dt_iop_rawprepare_flat_field_t flat_field
Region of interest passed through the pixelpipe.
typedef double((*spd)(unsigned long int wavelength, double TempK))