117 return _(
"unbreak input profile");
122 return dt_iop_set_description(self, _(
"correct input color profiles meant to be applied on non-linear RGB"),
124 _(
"linear, RGB, display-referred"),
125 _(
"non-linear, RGB"),
126 _(
"non-linear, RGB, display-referred"));
148 memset(&
p, 0,
sizeof(
p));
151 p.grey_point = 18.00f;
152 p.security_factor = 0.0f;
155 p.dynamic_range = 16.0f;
156 p.shadows_range = -12.0f;
158 self->version(), &
p,
sizeof(
p), 1);
161 p.dynamic_range = 14.0f;
162 p.shadows_range = -10.50f;
164 self->version(), &
p,
sizeof(
p), 1);
167 p.dynamic_range = 12.0f;
168 p.shadows_range = -9.0f;
170 self->version(), &
p,
sizeof(
p), 1);
173 p.dynamic_range = 10.0f;
174 p.shadows_range = -7.50f;
176 self->version(), &
p,
sizeof(
p), 1);
179 p.dynamic_range = 8.0f;
180 p.shadows_range = -6.0f;
182 self->version(), &
p,
sizeof(
p), 1);
187 const int new_version)
189 if(old_version == 1 && new_version == 2)
191 typedef struct dt_iop_profilegamma_params_v1_t
195 } dt_iop_profilegamma_params_v1_t;
197 dt_iop_profilegamma_params_v1_t *o = (dt_iop_profilegamma_params_v1_t *)old_params;
203 n->linear = o->linear;
213 const void *
const ivoid,
void *
const ovoid)
233 const float noise = powf(2.0f, -16.0f);
237 float tmp = ((
const float *)ivoid)[
k] / grey;
247 ((
float *)
ovoid)[
k] = tmp;
258 const float *in = ((
float *)ivoid) + (size_t)
ch *
k * roi_out->
width;
261 for(
int j = 0; j < roi_out->
width; j++, in +=
ch,
out +=
ch)
263 for(
int i = 0;
i < 3;
i++)
267 out[
i] = data->
table[CLAMP((
int)(in[
i] * 0x10000ul), 0, 0xffff)];
289 p->grey_point = 100.f * grey;
304 float noise = powf(2.0f, -16.0f);
309 EVmin *= (1.0f +
p->security_factor / 100.0f);
311 p->shadows_range = EVmin;
326 float noise = powf(2.0f, -16.0f);
329 float EVmin =
p->shadows_range;
334 EVmax *= (1.0f +
p->security_factor / 100.0f);
336 p->dynamic_range = EVmax - EVmin;
350 float noise = powf(2.0f, -16.0f);
354 p->grey_point = 100.f * grey;
359 EVmin *= (1.0f +
p->security_factor / 100.0f);
364 EVmax *= (1.0f +
p->security_factor / 100.0f);
366 p->shadows_range = EVmin;
367 p->dynamic_range = EVmax - EVmin;
394 gtk_stack_set_visible_child_name(GTK_STACK(
g->mode_stack),
"log");
398 gtk_stack_set_visible_child_name(GTK_STACK(
g->mode_stack),
"gamma");
401 else if(w ==
g->security_factor)
403 float prev = *(
float *)previous;
404 float ratio = (
p->security_factor - prev) / (prev + 100.0f);
406 float EVmin =
p->shadows_range;
407 EVmin = EVmin + ratio * EVmin;
409 float EVmax =
p->dynamic_range +
p->shadows_range;
410 EVmax = EVmax + ratio * EVmax;
412 p->dynamic_range = EVmax - EVmin;
413 p->shadows_range = EVmin;
425 if (picker ==
g->grey_point)
427 else if(picker ==
g->shadows_range)
429 else if(picker ==
g->dynamic_range)
431 else if(picker ==
g->auto_button)
434 fprintf(stderr,
"[profile_gamma] unknown color picker\n");
443 const float linear =
p->linear;
444 const float gamma =
p->gamma;
446 d->linear =
p->linear;
453 for(
int k = 0;
k < 0x10000;
k++)
d->table[
k] = 1.0 *
k / 0x10000;
460 for(
int k = 0;
k < 0x10000;
k++)
d->table[
k] = powf(1.00 *
k / 0x10000, gamma);
467 a = 1.0 / (1.0 +
linear * (
g - 1));
477 for(
int k = 0;
k < 0x10000;
k++)
481 tmp = c *
k / 0x10000;
483 tmp = powf(a *
k / 0x10000 + b,
g);
490 const float x[4] = { 0.7f, 0.8f, 0.9f, 1.0f };
492 = {
d->table[CLAMP((
int)(
x[0] * 0x10000ul), 0, 0xffff)],
493 d->table[CLAMP((
int)(
x[1] * 0x10000ul), 0, 0xffff)],
494 d->table[CLAMP((
int)(
x[2] * 0x10000ul), 0, 0xffff)],
495 d->table[CLAMP((
int)(
x[3] * 0x10000ul), 0, 0xffff)] };
498 d->dynamic_range =
p->dynamic_range;
499 d->grey_point =
p->grey_point;
500 d->shadows_range =
p->shadows_range;
501 d->security_factor =
p->security_factor;
541 g->mode_stack = gtk_stack_new();
542 gtk_stack_set_homogeneous(GTK_STACK(
g->mode_stack),
FALSE);
550 gtk_widget_set_tooltip_text(
g->linear, _(
"linear part"));
554 gtk_widget_set_tooltip_text(
g->gamma, _(
"gamma exponential factor"));
556 gtk_stack_add_named(GTK_STACK(
g->mode_stack), vbox_gamma,
"gamma");
565 gtk_widget_set_tooltip_text(
g->grey_point, _(
"adjust to match the average luma of the subject"));
571 gtk_widget_set_tooltip_text(
g->shadows_range, _(
"number of stops between middle gray and pure black\nthis is a reading a posemeter would give you on the scene"));
577 gtk_widget_set_tooltip_text(
g->dynamic_range, _(
"number of stops between pure black and pure white\nthis is a reading a posemeter would give you on the scene"));
583 gtk_widget_set_tooltip_text(
g->security_factor, _(
"enlarge or shrink the computed dynamic range\nthis is useful when noise perturbates the measurements"));
587 gtk_widget_set_tooltip_text(
g->auto_button, _(
"make an optimization with some guessing"));
588 gtk_box_pack_start(GTK_BOX(vbox_log),
g->auto_button,
TRUE,
TRUE, 0);
590 gtk_stack_add_named(GTK_STACK(
g->mode_stack), vbox_log,
"log");
596 gtk_widget_set_tooltip_text(
g->mode, _(
"tone mapping method"));
void dt_bauhaus_slider_set_soft_range(GtkWidget *widget, float soft_min, float soft_max)
void dt_bauhaus_slider_set_digits(GtkWidget *widget, int val)
void dt_bauhaus_slider_set_soft_max(GtkWidget *widget, float val)
void dt_bauhaus_slider_set(GtkWidget *widget, float pos)
void dt_bauhaus_widget_set_label(GtkWidget *widget, const char *label)
GtkWidget * dt_bauhaus_combobox_new(dt_bauhaus_t *bh, dt_gui_module_t *self)
void dt_bauhaus_slider_set_format(GtkWidget *widget, const char *format)
void dt_iop_color_picker_reset(dt_iop_module_t *module, gboolean keep)
GtkWidget * dt_color_picker_new(dt_iop_module_t *module, dt_iop_color_picker_kind_t kind, GtkWidget *w)
struct _GtkWidget GtkWidget
GtkWidget, opaque, spelled exactly as GTK spells it.
const dt_colormatrix_t dt_aligned_pixel_t out
struct dt_bauhaus_t * dt_bauhaus_get_global(void)
#define dt_dev_add_history_item(dev, module, enable, redraw)
@ DT_DEV_PIXELPIPE_DISPLAY_MASK
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 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)
@ IOP_FLAGS_INCLUDE_IN_STYLES
@ IOP_FLAGS_SUPPORTS_BLENDING
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)
static void dt_iop_estimate_exp(const float *const x, const float *const y, const int num, float *coeff)
static float dt_iop_eval_exp(const float *const coeff, const float x)
GtkWidget * dt_ui_section_label_new(const gchar *str)
float *const restrict const size_t k
float *const restrict const size_t const size_t ch
static float fastlog2(float x)
static float Log2Thres(float x, float Thres)
#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.
#define DT_MODULE_INTROSPECTION(MODVER, PARAMSTYPE)
DT_MODULE() for a module whose params struct is introspected.
#define __OMP_PARALLEL_FOR__(...)
#define __OMP_FOR_SIMD__(...)
const char ** description(struct dt_iop_module_t *self)
void gui_reset(dt_iop_module_t *self)
void gui_update(dt_iop_module_t *self)
Refresh GUI controls from current params and configuration.
__DT_CLONE_TARGETS__ int process(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)
static void apply_autotune(dt_iop_module_t *self)
void gui_init(dt_iop_module_t *self)
void gui_changed(dt_iop_module_t *self, GtkWidget *w, void *previous)
static void apply_auto_dynamic_range(dt_iop_module_t *self)
void commit_params(dt_iop_module_t *self, dt_iop_params_t *p1, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
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 init_presets(dt_iop_module_so_t *self)
void init_pipe(dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
dt_iop_profilegamma_mode_t
static void apply_auto_black(dt_iop_module_t *self)
static void apply_auto_grey(dt_iop_module_t *self)
void color_picker_apply(dt_iop_module_t *self, GtkWidget *picker, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
int legacy_params(dt_iop_module_t *self, const void *const old_params, const int old_version, void *new_params, const int new_version)
dt_iop_buffer_dsc_t dsc_in
struct dt_iop_module_t *void * data
dt_iop_params_t * default_params
struct dt_iop_module_gui_t * gui
struct dt_develop_t * dev
dt_aligned_pixel_t picked_color_min
dt_aligned_pixel_t picked_color_max
dt_aligned_pixel_t picked_color
float unbounded_coeffs[3]
dt_iop_profilegamma_mode_t mode
GtkWidget * security_factor
GtkWidget * dynamic_range
GtkWidget * shadows_range
dt_iop_profilegamma_mode_t mode
Region of interest passed through the pixelpipe.
#define __DT_CLONE_TARGETS__