42#define DT_IOP_COLORPRIMARIES_NODE_COUNT 6
43#define DT_IOP_COLORPRIMARIES_EDGE_COUNT 6
44#define DT_IOP_COLORPRIMARIES_RADIAL_COUNT (DT_IOP_COLORPRIMARIES_NODE_COUNT + DT_IOP_COLORPRIMARIES_EDGE_COUNT)
45#define DT_IOP_COLORPRIMARIES_BLACK_WHITE_COUNT (2 * DT_IOP_COLORPRIMARIES_NODE_COUNT)
46#define DT_IOP_COLORPRIMARIES_AXIS_ANCHORS 64
47#define DT_IOP_COLORPRIMARIES_MAX_ANCHORS \
48 (DT_IOP_COLORPRIMARIES_NODE_COUNT + DT_IOP_COLORPRIMARIES_EDGE_COUNT + DT_IOP_COLORPRIMARIES_RADIAL_COUNT \
49 + DT_IOP_COLORPRIMARIES_BLACK_WHITE_COUNT + DT_IOP_COLORPRIMARIES_AXIS_ANCHORS)
50#define DT_IOP_COLORPRIMARIES_VIEWER_CONTROL_NODES \
51 (DT_IOP_COLORPRIMARIES_NODE_COUNT + DT_IOP_COLORPRIMARIES_EDGE_COUNT + DT_IOP_COLORPRIMARIES_RADIAL_COUNT \
52 + DT_IOP_COLORPRIMARIES_BLACK_WHITE_COUNT)
53#define DT_IOP_COLORPRIMARIES_SQRT3 1.7320508075688772f
54#define DT_IOP_COLORPRIMARIES_INV_SQRT2 0.7071067811865475f
142 return _(
"color primaries");
147 return _(
"RGB primaries|primary colors");
153 _(
"edit RGB/CYM primary control nodes in dt UCS and interpolate their RGB shifts "
154 "through a cylindrical local field"),
155 _(
"creative"), _(
"linear, RGB, display-referred"), _(
"linear, RGB"),
156 _(
"linear, RGB, display-referred"));
207 memset(
p, 0,
sizeof(*
p));
208 p->white_level = 1.f;
209 p->gamut_coverage = 67.f;
213 p->neutral_protection = 0.f;
220 return !memcmp(a, b,
sizeof(*a));
267 const float mu = (corner[0] + corner[1] + corner[2]) / 3.f;
273 const float weight_b)
275 const float angle_a = hue_a *
M_PI_F / 180.f;
276 const float angle_b = hue_b *
M_PI_F / 180.f;
277 return atan2f(weight_a * sinf(angle_a) + weight_b * sinf(angle_b),
278 weight_a * cosf(angle_a) + weight_b * cosf(angle_b));
284 const float ds = a[1] - b[1];
285 const float db = a[2] - b[2];
286 return sqrtf(dh * dh + ds * ds + db * db);
291 RGB[0] = white ? 1.f : 0.f;
292 RGB[1] = white ? 1.f : 0.f;
293 RGB[2] = white ? 1.f : 0.f;
304 halfway_rgb[3] = 0.f;
308 const float saturation_delta,
const float brightness_delta,
316 float source_L = 0.f;
317 float source_rho = 0.f;
318 float source_theta = 0.f;
319 float source_axis_L = 0.f;
320 float target_axis_L = 0.f;
321 float unused_rho = 0.f;
322 float unused_theta = 0.f;
323 float source_brightness = 0.f;
324 float target_brightness = 0.f;
325 float requested_scale = 1.f;
330 if(source_rho <= 1e-6f)
return FALSE;
343 source_brightness = CLAMP(source_hsb[2], 0.f, 1.f);
344 target_brightness = CLAMP(source_brightness + brightness_delta, 0.f, 1.f);
350 if(source_hsb[1] > 1e-6f)
351 requested_scale = fmaxf(source_hsb[1] + saturation_delta, 0.f) / source_hsb[1];
353 anchor->
L = source_L;
354 anchor->
rho = source_rho;
355 anchor->
theta = source_theta;
356 anchor->
delta_L = target_axis_L - source_axis_L;
364 const float hue_delta,
const float saturation_delta,
365 const float brightness_delta,
374 float distance_source = 0.f;
375 float distance_axis = 0.f;
376 float weight_source = 0.5f;
377 float source_L = 0.f;
378 float source_rho = 0.f;
379 float source_theta = 0.f;
382 if(source_rho <= 1e-6f)
return FALSE;
397 axis_hsb[0] = source_hsb[0];
400 if(distance_source + distance_axis > 1e-6f)
401 weight_source = distance_axis / (distance_source + distance_axis);
404 weight_source * brightness_delta, lut_profile, anchor);
409 const float hue_delta,
const float saturation_delta,
410 const float brightness_delta,
418 float distance_source = 0.f;
419 float distance_extreme = 0.f;
420 float weight_source = 0.5f;
422 for(
int c = 0; c < 3; c++) halfway_rgb[c] = 0.5f * (source_rgb[c] + extreme_rgb[c]);
423 halfway_rgb[3] = 0.f;
429 extreme_hsb[0] = source_hsb[0];
432 if(distance_source + distance_extreme > 1e-6f)
433 weight_source = distance_extreme / (distance_source + distance_extreme);
436 weight_source * brightness_delta, lut_profile, anchor);
443 float source_L = 0.f;
444 float source_rho = 0.f;
445 float source_theta = 0.f;
462 _node_base_rgb(node, CLAMP(
p->gamut_coverage * 0.01f, 0.f, 1.f), source_rgb);
464 p->brightness[node], lut_profile, anchor);
469 float *
const hue_delta,
float *
const saturation_delta,
470 float *
const brightness_delta)
477 float distance_a = 0.f;
478 float distance_b = 0.f;
479 float weight_a = 0.5f;
480 float weight_b = 0.5f;
482 _node_base_rgb(edge.
a, CLAMP(
p->gamut_coverage * 0.01f, 0.f, 1.f), source_a);
483 _node_base_rgb(edge.
b, CLAMP(
p->gamut_coverage * 0.01f, 0.f, 1.f), source_b);
496 for_each_channel(c, aligned(source_a, source_b, source_rgb)) source_rgb[c] = 0.5f * (source_a[c] + source_b[c]);
504 if(distance_a + distance_b > 1e-6f)
506 weight_a = distance_b / (distance_a + distance_b);
507 weight_b = distance_a / (distance_a + distance_b);
511 *saturation_delta = (weight_a *
p->saturation[edge.
a] + weight_b *
p->saturation[edge.
b]) * 0.01f;
512 *brightness_delta = weight_a *
p->brightness[edge.
a] + weight_b *
p->brightness[edge.
b];
519 for(
int c = 0; c < 3; c++)
521 control_nodes[*count].
input_rgb[c] = input_rgb[c];
522 control_nodes[*count].
output_rgb[c] = output_rgb[c];
530 anchors[*anchor_count] = *anchor;
539 float hue_delta = 0.f;
540 float saturation_delta = 0.f;
541 float brightness_delta = 0.f;
543 if(!
_build_edge_edit(
p, edge, lut_profile, source_rgb, &hue_delta, &saturation_delta, &brightness_delta))
556 _node_base_rgb(node, CLAMP(
p->gamut_coverage * 0.01f, 0.f, 1.f), source_rgb);
558 p->saturation[node] * 0.01f,
p->brightness[node],
559 lut_profile, anchor, midpoint_rgb);
564 const gboolean toward_white,
571 _node_base_rgb(node, CLAMP(
p->gamut_coverage * 0.01f, 0.f, 1.f), source_rgb);
574 p->saturation[node] * 0.01f,
p->brightness[node],
575 lut_profile, anchor, midpoint_rgb);
585 float hue_delta = 0.f;
586 float saturation_delta = 0.f;
587 float brightness_delta = 0.f;
589 if(!
_build_edge_edit(
p, edge, lut_profile, source_rgb, &hue_delta, &saturation_delta, &brightness_delta))
593 lut_profile, anchor, midpoint_rgb);
621 float hue_delta = 0.f;
622 float saturation_delta = 0.f;
623 float brightness_delta = 0.f;
633 for(
int white = 0; white < 2; white++)
688 HSB[1] = CLAMP(source_hsb[1] +
p->saturation[node] * 0.01f, 0.f, 1.f);
689 HSB[2] = CLAMP(source_hsb[2] +
p->brightness[node], 0.f, 1.f);
699 const float inv_sigma_L = 1.f / fmaxf(
p->sigma_L * 0.01f, 1e-6f);
700 const float inv_sigma_rho = 1.f / fmaxf(
p->sigma_rho, 1e-6f);
701 const float inv_sigma_theta = 1.f / fmaxf(
p->sigma_theta, 1e-6f);
703 int anchor_count = 0;
747 for(
int white = 0; white < 2; white++)
753 &extreme_anchor, midway_rgb))
761 anchors[anchor_count].
rho = 0.f;
762 anchors[anchor_count].
theta = 0.f;
763 anchors[anchor_count].
delta_L = 0.f;
771 inv_sigma_rho, inv_sigma_theta, fmaxf(
p->neutral_protection, 1e-6f));
794 d->white_level = 1.f;
795 d->lut_profile = NULL;
796 d->work_profile = NULL;
812 d->white_level = exp2f(
p->white_level);
827 d->white_level = 1.f;
841 cl_mem dev_in, cl_mem dev_out)
847 const int devid = pipe->
devid;
849 const float white_level = fmaxf(
d->white_level, 1e-6f);
850 const float normalize = 1.f / white_level;
851 const float denormalize = white_level;
852 const float black = 0.f;
853 cl_mem clut_cl = NULL;
854 cl_int err = CL_SUCCESS;
868 if(err != CL_SUCCESS)
goto cleanup;
871 d->lut_profile,
"colorequal work to HLG Rec2020"))
873 err = CL_INVALID_OPERATION;
883 err = CL_MEM_OBJECT_ALLOCATION_FAILURE;
894 if(err != CL_SUCCESS)
goto cleanup;
897 d->work_profile,
"colorequal HLG Rec2020 to work"))
899 err = CL_INVALID_OPERATION;
914 return err == CL_SUCCESS;
920 const void *
const ibuf,
void *
const obuf)
934 const float white_level = fmaxf(
d->white_level, 1e-6f);
938 const float *in = (
const float *)ibuf +
k *
ch;
939 float *
out = (
float *)obuf +
k *
ch;
940 out[0] = in[0] / white_level;
941 out[1] = in[1] / white_level;
942 out[2] = in[2] / white_level;
943 if(
ch > 3)
out[3] = in[3];
947 "colorprimaries work to HLG Rec2020");
952 "colorprimaries HLG Rec2020 to work");
956 float *
out = (
float *)obuf +
k *
ch;
957 out[0] *= white_level;
958 out[1] *= white_level;
959 out[2] *= white_level;
1021 for(
int stop = 0; stop <= 6; stop++)
1023 const float hue_shift = -
M_PI_F + 2.f *
M_PI_F * (float)stop / 6.f;
1044 memcpy(shell_rgb, target_rgb,
sizeof(shell_rgb));
1054 (
dt_aligned_pixel_t){ target_hsb[0], target_hsb[1], CLAMP(source_hsb[2] - 0.05f, 0.f, 1.f),
1058 (
dt_aligned_pixel_t){ target_hsb[0], target_hsb[1], source_hsb[2], 0.f }, display_profile);
1060 (
dt_aligned_pixel_t){ target_hsb[0], target_hsb[1], CLAMP(source_hsb[2] + 0.05f, 0.f, 1.f),
1068 gtk_widget_queue_draw(
g->node_hue[node]);
1069 gtk_widget_queue_draw(
g->node_saturation[node]);
1070 gtk_widget_queue_draw(
g->node_brightness[node]);
1093 if(!
g->viewer_lut_dirty &&
g->viewer_lut_valid &&
g->viewer_lut_generation == cache_generation
1094 &&
g->viewer_display_profile == display_profile)
1101 g->viewer_lut_dirty =
FALSE;
1102 g->viewer_lut_valid =
FALSE;
1103 g->viewer_lut_generation = 0;
1104 g->viewer_display_profile = display_profile;
1105 g->viewer_control_node_count = 0;
1113 memcpy(&gd->
params,
p,
sizeof(*
p));
1122 g->viewer_control_node_count
1129 g->viewer_lut_dirty =
FALSE;
1130 g->viewer_lut_valid =
TRUE;
1131 g->viewer_lut_generation = cache_generation;
1132 g->viewer_display_profile = display_profile;
1172 g->viewer_lut.clut = NULL;
1180 gtk_widget_set_hexpand(section,
TRUE);
1181 gtk_box_pack_start(GTK_BOX(box), section,
FALSE,
FALSE, 0);
1190 const dt_iop_module_t *sampled_module = piece && piece->module ? piece->module : self;
1192 if(picker !=
g->white_level)
return;
1198 p->white_level = log2f(fmaxf(max_Ych[0], 1e-6f));
1213 const float *
const restrict in = (
const float *)
i;
1217 for(
size_t k = 0;
k < (size_t)roi_out->
width * roi_out->
height * 4;
k += 4)
1221 if(isfinite(Ych[0]))
1222 max_Y = fmaxf(max_Y, Ych[0]);
1225 p->white_level = log2f(fmaxf(max_Y, 1e-6f));
1233 g->viewer_lut_dirty =
TRUE;
1234 g->viewer_lut_valid =
FALSE;
1235 g->viewer_lut_generation = 0;
1236 g->viewer_lut.clut = NULL;
1237 g->viewer_lut.clut_level = 0;
1238 g->viewer_lut.lut_profile = NULL;
1239 g->viewer_lut.work_profile = NULL;
1240 g->preview_signal_connected =
FALSE;
1241 g->viewer_display_profile = NULL;
1245 g->tabs = GTK_NOTEBOOK(gtk_notebook_new());
1246 gtk_notebook_set_show_border(
g->tabs,
FALSE);
1247 gtk_box_pack_start(GTK_BOX(self->
widget), GTK_WIDGET(
g->tabs),
TRUE,
TRUE, 0);
1250 GtkWidget *colors_tab = gtk_label_new(_(
"colors"));
1252 gtk_notebook_append_page(
g->tabs, colors_page, colors_tab);
1253 gtk_container_child_set(GTK_CONTAINER(
g->tabs), colors_page,
"tab-expand",
TRUE,
"tab-fill",
TRUE, NULL);
1256 self->
widget = colors_page;
1259 char hue_name[16] = { 0 };
1260 char saturation_name[24] = { 0 };
1261 char brightness_name[24] = { 0 };
1262 snprintf(hue_name,
sizeof(hue_name),
"hue[%d]", node);
1263 snprintf(saturation_name,
sizeof(saturation_name),
"saturation[%d]", node);
1264 snprintf(brightness_name,
sizeof(brightness_name),
"brightness[%d]", node);
1283 self->
widget = module_root;
1286 GtkWidget *options_tab = gtk_label_new(_(
"options"));
1288 gtk_notebook_append_page(
g->tabs, options_page, options_tab);
1289 gtk_container_child_set(GTK_CONTAINER(
g->tabs), options_page,
"tab-expand",
TRUE,
"tab-fill",
TRUE, NULL);
1291 self->
widget = options_page;
1321 self->
widget = module_root;
1327 gtk_widget_show_all(self->
widget);
1334 memset(gd, 0,
sizeof(*gd));
1339 const int lut_program = 28;
1340 const int basic_program = 2;
void cleanup(dt_imageio_module_format_t *self)
void dt_bauhaus_slider_set_soft_range(GtkWidget *widget, float soft_min, float soft_max)
void dt_bauhaus_slider_clear_stops(GtkWidget *widget)
void dt_bauhaus_slider_set_default(GtkWidget *widget, float def)
void dt_bauhaus_slider_set_stop(GtkWidget *widget, float stop, float r, float g, float b)
void dt_bauhaus_combobox_set_default(GtkWidget *widget, int def)
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)
void dt_bauhaus_slider_set_format(GtkWidget *widget, const char *format)
static __DT_CLONE_TARGETS__ void normalize(float *const buffer, const size_t width, const size_t height, const float norm)
static const dt_aligned_pixel_simd_t const dt_adaptation_t const float p
GtkWidget * dt_color_picker_new(dt_iop_module_t *module, dt_iop_color_picker_kind_t kind, GtkWidget *w)
void dt_colorrings_profile_rgb_to_dt_ucs_hsb(const dt_aligned_pixel_t RGB, const float white, const dt_iop_order_iccprofile_info_t *profile, dt_aligned_pixel_t HSB)
void dt_colorrings_profile_rgb_to_display_rgb(const dt_aligned_pixel_t RGB, const dt_iop_order_iccprofile_info_t *profile, const dt_iop_order_iccprofile_info_t *display_profile, dt_aligned_pixel_t display_rgb)
void dt_colorrings_fill_lut_sparse_local_field(float *lut, const int level, const dt_colorrings_sparse_anchor_t *const anchors, const int anchor_count, const float inv_sigma_L, const float inv_sigma_rho, const float inv_sigma_theta, const float rho0)
void dt_colorrings_hsb_to_profile_rgb(const dt_aligned_pixel_t HSB, const float white, const dt_iop_order_iccprofile_info_t *profile, dt_aligned_pixel_t RGB)
void dt_colorrings_gray_basis_to_rgb(const float L, const float u, const float v, float rgb[3])
void dt_colorrings_gray_axis_rgb_from_L(const float L, dt_aligned_pixel_t RGB)
void dt_colorrings_rgb_to_gray_cyl(const float rgb[3], float *L, float *rho, float *theta)
float dt_colorrings_wrap_hue_pi(float hue)
float dt_colorrings_wrap_hue_2pi(float hue)
void dt_colorrings_project_to_cube_shell(const dt_aligned_pixel_t axis, dt_aligned_pixel_t RGB)
void dt_colorrings_hsb_to_display_rgb(const dt_aligned_pixel_t HSB, const float white, const dt_iop_order_iccprofile_info_t *display_profile, dt_aligned_pixel_t RGB)
float dt_colorrings_wrap_pi(float x)
void dt_colorrings_profile_rgb_to_Ych(const dt_aligned_pixel_t RGB, const dt_iop_order_iccprofile_info_t *profile, dt_aligned_pixel_t Ych)
float dt_colorrings_graph_white(void)
void dt_colorrings_brightness_to_axis_rgb(const float brightness, const float white, const dt_iop_order_iccprofile_info_t *profile, dt_aligned_pixel_t RGB)
#define DT_COLORRINGS_CLUT_LEVEL
static void _refresh_slider_gradients(dt_iop_module_t *self)
void commit_params(struct dt_iop_module_t *self, dt_iop_params_t *p1, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
static const char * _node_name(const dt_iop_colorprimaries_node_t node)
void init(dt_iop_module_t *module)
static void _append_anchor(dt_colorrings_sparse_anchor_t *const anchors, int *const anchor_count, const dt_colorrings_sparse_anchor_t *const anchor)
const char ** description(struct dt_iop_module_t *self)
static void _apply_anchor_to_rgb(const dt_aligned_pixel_t source_rgb, const dt_colorrings_sparse_anchor_t *const anchor, dt_aligned_pixel_t target_rgb)
static float _hsb_distance(const dt_aligned_pixel_t a, const dt_aligned_pixel_t b)
static void _node_target_hsb(const dt_iop_colorprimaries_params_t *const p, const dt_iop_colorprimaries_node_t node, const dt_iop_order_iccprofile_info_t *const lut_profile, dt_aligned_pixel_t HSB)
static void _store_viewer_control_node(dt_lut_viewer_control_node_t *const control_nodes, int *const count, const dt_aligned_pixel_t input_rgb, const dt_aligned_pixel_t output_rgb)
void gui_update(dt_iop_module_t *self)
static void _black_white_rgb(const gboolean white, dt_aligned_pixel_t RGB)
static void _node_corner_rgb(const dt_iop_colorprimaries_node_t node, dt_aligned_pixel_t RGB)
static gboolean _lut_fields_equal(const dt_iop_colorprimaries_params_t *const a, const dt_iop_colorprimaries_params_t *const b)
static int _build_viewer_control_nodes(const dt_iop_colorprimaries_params_t *const p, const dt_iop_order_iccprofile_info_t *const lut_profile, dt_lut_viewer_control_node_t *const control_nodes)
static void _set_slider_stop_from_profile_rgb(GtkWidget *slider, const float stop, const dt_aligned_pixel_t RGB, const dt_iop_order_iccprofile_info_t *lut_profile, const dt_iop_order_iccprofile_info_t *display_profile)
static gboolean _build_edge_radial_midpoint_anchor(const dt_iop_colorprimaries_params_t *const p, const dt_iop_colorprimaries_edge_t edge, const dt_iop_order_iccprofile_info_t *const lut_profile, dt_colorrings_sparse_anchor_t *const anchor, dt_aligned_pixel_t midpoint_rgb)
void init_pipe(struct dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
static gboolean _build_halfway_radial_anchor_from_source_rgb(const dt_aligned_pixel_t source_rgb, const float hue_delta, const float saturation_delta, const float brightness_delta, const dt_iop_order_iccprofile_info_t *const lut_profile, dt_colorrings_sparse_anchor_t *const anchor, dt_aligned_pixel_t halfway_rgb)
static GtkWidget * _new_section_label(GtkWidget *box, const char *label)
static gboolean _build_halfway_extreme_anchor_from_source_rgb(const dt_aligned_pixel_t source_rgb, const dt_aligned_pixel_t extreme_rgb, const float hue_delta, const float saturation_delta, const float brightness_delta, const dt_iop_order_iccprofile_info_t *const lut_profile, dt_colorrings_sparse_anchor_t *const anchor, dt_aligned_pixel_t halfway_rgb)
static gboolean _build_anchor_from_source_rgb(const dt_aligned_pixel_t source_rgb, const float hue_delta, const float saturation_delta, const float brightness_delta, const dt_iop_order_iccprofile_info_t *const lut_profile, dt_colorrings_sparse_anchor_t *const anchor)
static void _halfway_to_axis_rgb(const dt_aligned_pixel_t source_rgb, dt_aligned_pixel_t halfway_rgb)
void gui_init(dt_iop_module_t *self)
static void _node_base_rgb(const dt_iop_colorprimaries_node_t node, const float gamut_coverage, dt_aligned_pixel_t RGB)
void gui_changed(dt_iop_module_t *self, GtkWidget *w, void *previous)
#define DT_IOP_COLORPRIMARIES_EDGE_COUNT
void gui_cleanup(dt_iop_module_t *self)
static gboolean _build_node_black_white_midpoint_anchor(const dt_iop_colorprimaries_params_t *const p, const dt_iop_colorprimaries_node_t node, const gboolean toward_white, const dt_iop_order_iccprofile_info_t *const lut_profile, dt_colorrings_sparse_anchor_t *const anchor, dt_aligned_pixel_t midpoint_rgb)
static void _update_gui_lut_cache(dt_iop_module_t *self)
void cleanup_global(dt_iop_module_so_t *module)
static gboolean _build_edge_edit(const dt_iop_colorprimaries_params_t *const p, const dt_iop_colorprimaries_edge_t edge, const dt_iop_order_iccprofile_info_t *const lut_profile, dt_aligned_pixel_t source_rgb, float *const hue_delta, float *const saturation_delta, float *const brightness_delta)
int default_colorspace(dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece)
static gboolean _build_node_anchor(const dt_iop_colorprimaries_params_t *const p, const dt_iop_colorprimaries_node_t node, const dt_iop_order_iccprofile_info_t *const lut_profile, dt_colorrings_sparse_anchor_t *const anchor)
dt_iop_colorprimaries_node_t
@ DT_IOP_COLORPRIMARIES_BLUE
@ DT_IOP_COLORPRIMARIES_GREEN
@ DT_IOP_COLORPRIMARIES_MAGENTA
@ DT_IOP_COLORPRIMARIES_YELLOW
@ DT_IOP_COLORPRIMARIES_CYAN
@ DT_IOP_COLORPRIMARIES_RED
#define DT_IOP_COLORPRIMARIES_SQRT3
#define DT_IOP_COLORPRIMARIES_INV_SQRT2
dt_iop_colorprimaries_interpolation_t
@ DT_IOP_COLORPRIMARIES_TETRAHEDRAL
@ DT_IOP_COLORPRIMARIES_PYRAMID
@ DT_IOP_COLORPRIMARIES_TRILINEAR
void cleanup_pipe(struct dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
static gboolean _build_edge_anchor(const dt_iop_colorprimaries_params_t *const p, const dt_iop_colorprimaries_edge_t edge, const dt_iop_order_iccprofile_info_t *const lut_profile, dt_colorrings_sparse_anchor_t *const anchor)
static void _init_default_params(dt_iop_colorprimaries_params_t *p)
static gboolean _build_node_radial_midpoint_anchor(const dt_iop_colorprimaries_params_t *const p, const dt_iop_colorprimaries_node_t node, const dt_iop_order_iccprofile_info_t *const lut_profile, dt_colorrings_sparse_anchor_t *const anchor, dt_aligned_pixel_t midpoint_rgb)
static float _mix_hue_delta_weighted(const float hue_a, const float hue_b, const float weight_a, const float weight_b)
static void _node_source_hsb(const dt_iop_colorprimaries_params_t *const p, const dt_iop_colorprimaries_node_t node, const dt_iop_order_iccprofile_info_t *const lut_profile, dt_aligned_pixel_t HSB)
#define DT_IOP_COLORPRIMARIES_NODE_COUNT
static void _pipe_rgb_to_Ych(dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, const dt_aligned_pixel_t RGB, dt_aligned_pixel_t Ych)
void init_global(dt_iop_module_so_t *module)
__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 ibuf, void *const obuf)
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 *i)
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 const dt_iop_colorprimaries_edge_t _chroma_edges[6]
void color_picker_apply(dt_iop_module_t *self, GtkWidget *picker, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
static void _build_clut(dt_iop_colorprimaries_data_t *d, const dt_iop_colorprimaries_params_t *p, const dt_iop_order_iccprofile_info_t *lut_profile)
#define DT_IOP_COLORPRIMARIES_VIEWER_CONTROL_NODES
#define DT_IOP_COLORPRIMARIES_MAX_ANCHORS
static void _set_slider_stop_from_hsb(GtkWidget *slider, const float stop, const dt_aligned_pixel_t HSB, const dt_iop_order_iccprofile_info_t *display_profile)
#define DT_IOP_COLORPRIMARIES_AXIS_ANCHORS
@ DT_COLORSPACE_HLG_REC2020
const dt_colormatrix_t dt_aligned_pixel_t out
static dt_aligned_pixel_t RGB
void dt_lut3d_apply(const float *const in, float *const out, const size_t pixel_nb, const float *const clut, const uint16_t level, const float normalization, const dt_lut3d_interpolation_t interpolation)
Apply one interpolation model over a packed RGB CLUT.
void dt_print(dt_debug_thread_t thread, const char *msg,...)
#define dt_free_align(ptr)
static void * dt_calloc_align(size_t size)
#define for_each_channel(_var,...)
static float * dt_alloc_align_float(size_t pixels)
#define DT_MODULE_INTROSPECTION(MODVER, PARAMSTYPE)
#define __DT_CLONE_TARGETS__
#define __OMP_PARALLEL_FOR__(...)
static const dt_aligned_pixel_simd_t value
static double dt_get_wtime(void)
#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_dev_add_history_item(dev, module, enable, redraw)
#define dt_pthread_rwlock_destroy
#define dt_pthread_rwlock_wrlock
#define dt_pthread_rwlock_t
#define dt_pthread_rwlock_init
#define dt_pthread_rwlock_unlock
#define dt_pthread_rwlock_rdlock
void dt_gui_add_class(GtkWidget *widget, const gchar *class_name)
static GtkWidget * dt_ui_section_label_new(const gchar *str)
#define DT_GUI_BOX_SPACING
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)
void dt_iop_default_init(dt_iop_module_t *module)
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
#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)
dt_iop_order_iccprofile_info_t * dt_ioppr_get_pipe_output_profile_info(const struct dt_dev_pixelpipe_t *pipe)
dt_iop_order_iccprofile_info_t * dt_ioppr_add_profile_info_to_list(struct dt_develop_t *dev, const dt_colorspaces_color_profile_type_t profile_type, const char *profile_filename, const int intent)
dt_iop_order_iccprofile_info_t * dt_ioppr_get_pipe_current_profile_info(dt_iop_module_t *module, const struct dt_dev_pixelpipe_t *pipe)
void dt_ioppr_transform_image_colorspace_rgb(const float *const restrict image_in, float *const restrict image_out, const int width, const int height, const dt_iop_order_iccprofile_info_t *const profile_info_from, const dt_iop_order_iccprofile_info_t *const profile_info_to, const char *message)
int dt_ioppr_transform_image_colorspace_rgb_cl(const int devid, cl_mem dev_img_in, cl_mem dev_img_out, const int width, const int height, const dt_iop_order_iccprofile_info_t *const profile_info_from, const dt_iop_order_iccprofile_info_t *const profile_info_to, const char *message)
float *const restrict const size_t k
float *const restrict const size_t const size_t ch
@ DT_LUT3D_INTERP_PYRAMID
@ DT_LUT3D_INTERP_TETRAHEDRAL
@ DT_LUT3D_INTERP_TRILINEAR
void dt_lut_viewer_destroy(dt_lut_viewer_t **viewer)
void dt_lut_viewer_queue_draw(dt_lut_viewer_t *viewer)
void dt_lut_viewer_set_control_nodes(dt_lut_viewer_t *viewer, const dt_lut_viewer_control_node_t *control_nodes, size_t control_node_count)
GtkWidget * dt_lut_viewer_get_widget(dt_lut_viewer_t *viewer)
dt_lut_viewer_t * dt_lut_viewer_new(dt_gui_module_t *module)
void dt_lut_viewer_set_lut(dt_lut_viewer_t *viewer, const float *clut, uint16_t level, dt_pthread_rwlock_t *clut_lock, const dt_iop_order_iccprofile_info_t *lut_profile, const dt_iop_order_iccprofile_info_t *display_profile)
float dt_aligned_pixel_t[4]
int dt_opencl_enqueue_kernel_2d(const int dev, const int kernel, const size_t *sizes)
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)
struct _GtkWidget GtkWidget
unsigned __int64 uint64_t
struct dt_gui_gtk_t * gui
struct dt_develop_t * develop
dt_iop_buffer_dsc_t dsc_in
struct dt_iop_module_t *void * data
struct dt_dev_pixelpipe_t * preview_pipe
dt_iop_order_iccprofile_info_t * lut_profile
dt_lut3d_interpolation_t interpolation
dt_iop_order_iccprofile_info_t * work_profile
dt_iop_colorprimaries_node_t a
dt_iop_colorprimaries_node_t b
dt_iop_colorprimaries_data_t cache
uint64_t cache_generation
int kernel_lut3d_trilinear
dt_iop_colorprimaries_params_t params
int kernel_lut3d_tetrahedral
uint64_t viewer_lut_generation
gboolean viewer_lut_dirty
gboolean viewer_lut_valid
GtkWidget * gamut_coverage
dt_lut_viewer_control_node_t viewer_control_nodes[(6+6+(6+6)+(2 *6))]
GtkWidget * interpolation
const dt_iop_order_iccprofile_info_t * viewer_display_profile
gboolean preview_signal_connected
GtkWidget * neutral_protection
dt_iop_colorprimaries_data_t viewer_lut
size_t viewer_control_node_count
GtkWidget * node_brightness[6]
GtkWidget * node_saturation[6]
dt_iop_colorprimaries_interpolation_t interpolation
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
dt_aligned_pixel_t picked_color_min
dt_aligned_pixel_t picked_color_max
Region of interest passed through the pixelpipe.