52#define DT_SPLITTONING_RGB_POINT_COUNT 2
53#define DT_SPLITTONING_RGB_ROW_COUNT 3
54#define DT_SPLITTONING_RGB_COMPLETE_COUNT 3
55#define DT_SPLITTONING_RGB_PREVIEW_HEIGHT 60
131 "plugins/darkroom/splittoningrgb/dark_mixer_mode",
132 "plugins/darkroom/splittoningrgb/bright_mixer_mode"
144 return _(
"split-toning");
149 return _(
"split toning|split tone RGB");
155 _(
"blend two CAT16 plus RGB mixer corrections across brightness keyframes"),
156 _(
"creative or corrective"), _(
"linear, RGB, scene-referred"),
157 _(
"linear, RGB"), _(
"linear, RGB, scene-referred"));
195 if(temperature > 4000.f)
204 for(
int col = 0; col < 3; col++)
206 rows[0][col] =
p->red[
point][col];
207 rows[1][col] =
p->green[
point][col];
208 rows[2][col] =
p->blue[
point][col];
216 for(
int col = 0; col < 3; col++)
218 p->red[
point][col] =
M[0][col];
219 p->green[
point][col] =
M[1][col];
220 p->blue[
point][col] =
M[2][col];
232 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(
g->point[
point].normalize[
row]),
p->normalize[
point][
row]);
239 gtk_stack_set_visible_child_name(GTK_STACK(
g->point[
point].mixer_stack),
243 gtk_widget_queue_resize(
g->point[
point].mixer_stack);
244 gtk_widget_queue_resize(
g->point[
point].page);
245 gtk_widget_queue_resize(GTK_WIDGET(
g->tabs));
252 for(
int col = 0; col < 3; col++)
253 CAT[
row][col] =
row == col ? 1.f : 0.f;
268 for(
int col = 0; col < 3; col++)
278 chroma_adapt_pixel(dt_load_simd_aligned(XYZ_in), dt_load_simd_aligned(illuminant_LMS),
289 float rows[3][3] = { { 0.f } };
291 float mixer[3][3] = { { 0.f } };
292 float CAT[3][3] = { { 0.f } };
293 float combined[3][3] = { { 0.f } };
303 for(
int col = 0; col < 3; col++)
304 point_matrix[col][
row] = combined[
row][col];
326 for(
int col = 0; col < 3; col++)
327 interpolated[
row][col] = from[
row][col] + alpha * (to[
row][col] - from[
row][col]);
329 interpolated[0][3] = 0.f;
330 interpolated[1][3] = 0.f;
331 interpolated[2][3] = 0.f;
350 dt_colormatrix_t identity = { { 1.f, 0.f, 0.f, 0.f }, { 0.f, 1.f, 0.f, 0.f }, { 0.f, 0.f, 1.f, 0.f } };
351 const float segment = fmaxf(
d->bright_luminance -
d->dark_luminance,
NORM_MIN);
353 if(luminance <= d->dark_luminance)
355 const float alpha = CLAMP(1.f - (
d->dark_luminance - fmaxf(
luminance, 0.f)) / segment, 0.f, 1.f);
362 const float alpha = CLAMP(1.f - (
luminance -
d->bright_luminance) / segment, 0.f, 1.f);
367 const float alpha = CLAMP((
luminance -
d->dark_luminance) / segment, 0.f, 1.f);
377 = {
g->point[
point].simple_theta,
g->point[
point].simple_psi,
g->point[
point].simple_stretch_1,
378 g->point[
point].simple_stretch_2,
g->point[
point].simple_coupling_1,
379 g->point[
point].simple_coupling_2 };
380 float rows[3][3] = { { 0.f } };
382 float M[3][3] = { { 0.f } };
383 float roundtrip[3][3] = { { 0.f } };
410 = {
g->point[
point].primaries_achromatic_hue,
g->point[
point].primaries_achromatic_purity,
411 g->point[
point].primaries_red_hue,
g->point[
point].primaries_red_purity,
412 g->point[
point].primaries_green_hue,
g->point[
point].primaries_green_purity,
413 g->point[
point].primaries_blue_hue,
g->point[
point].primaries_blue_purity,
414 g->point[
point].primaries_gain };
415 float rows[3][3] = { { 0.f } };
417 float M[3][3] = { { 0.f } };
418 float roundtrip[3][3] = { { 0.f } };
445 if(
g &&
g->preview) gtk_widget_queue_draw(
g->preview);
468 if(
g->preview_surface)
470 cairo_surface_destroy(
g->preview_surface);
471 g->preview_surface = NULL;
473 g->preview_width = 0;
474 g->preview_height = 0;
500 const float basis[3][3] = { { 1.f, 0.f, 0.f }, { 0.f, 1.f, 0.f }, { 0.f, 0.f, 1.f } };
504 = {
g->point[
point].simple_theta,
g->point[
point].simple_psi,
g->point[
point].simple_stretch_1,
505 g->point[
point].simple_stretch_2,
g->point[
point].simple_coupling_1,
g->point[
point].simple_coupling_2 };
507 = {
g->point[
point].primaries_achromatic_hue,
g->point[
point].primaries_achromatic_purity,
508 g->point[
point].primaries_red_hue,
g->point[
point].primaries_red_purity,
509 g->point[
point].primaries_green_hue,
g->point[
point].primaries_green_purity,
510 g->point[
point].primaries_blue_hue,
g->point[
point].primaries_blue_purity,
511 g->point[
point].primaries_gain };
540 gboolean complete_widget =
FALSE;
544 complete_widget = complete_widget || changed ==
g->point[
point].normalize[
row];
545 for(
int col = 0; col < 3; col++) complete_widget = complete_widget || changed ==
g->point[
point].complete[
row][col];
550 float simple_error = INFINITY;
551 float primaries_error = INFINITY;
562 dt_control_log(_(
"simple mixer mode requires normalized rows with non-zero sums."));
571 dt_control_log(_(
"primaries mixer mode requires a non-singular 3x3 matrix with non-zero affine sums."));
584 const int point = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(changed),
"split-point"));
587 if(
g->preview_surface)
589 cairo_surface_destroy(
g->preview_surface);
590 g->preview_surface = NULL;
592 g->preview_width = 0;
593 g->preview_height = 0;
619 cairo_t *cr = cairo_create(surface);
637 for(
int i = 0;
i < 3;
i++)
state.rgb_to_xyz_transposed[
i][
i] = 1.f;
642 if(
state.bright_luminance <=
state.dark_luminance)
643 state.bright_luminance =
state.dark_luminance + fmaxf(
state.dark_luminance * 0.01f, 1e-4f);
646 const float grey =
width > 1 ? (float)
x / (
float)(
width - 1) : 0.f;
652 const dt_aligned_pixel_simd_t input_v = dt_load_simd_aligned(input);
655 _get_split_matrix(fmaxf(
XYZ[1], 0.f), &
state, combined_matrix);
658 dt_colormatrix_row_to_simd(combined_matrix, 0),
659 dt_colormatrix_row_to_simd(combined_matrix, 1),
660 dt_colormatrix_row_to_simd(combined_matrix, 2)));
663 cairo_set_source_rgb(cr, display[0], display[1], display[2]);
664 cairo_rectangle(cr,
x, 0, 1,
height);
669 cairo_surface_mark_dirty(surface);
676 GtkAllocation allocation;
678 gtk_widget_get_allocation(widget, &allocation);
679 if(allocation.width <= 0 || allocation.height <= 0)
return TRUE;
681 if(
IS_NULL_PTR(
g->preview_surface) ||
g->preview_width != allocation.width ||
g->preview_height != allocation.height)
683 if(
g->preview_surface) cairo_surface_destroy(
g->preview_surface);
686 g->preview_width = allocation.width;
687 g->preview_height = allocation.height;
691 cairo_set_source_surface(cr,
g->preview_surface, 0., 0.);
704 const int point = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(widget),
"split-point"));
705 gboolean changed_complete =
FALSE;
707 if(widget ==
g->point[
point].ev)
709 else if(widget ==
g->point[
point].temperature)
714 if(widget ==
g->point[
point].normalize[
row])
716 p->normalize[
point][
row] = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
717 changed_complete =
TRUE;
720 for(
int col = 0; col < 3; col++)
722 if(widget ==
g->point[
point].complete[
row][col])
726 changed_complete =
TRUE;
742 const int point = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(widget),
"split-point"));
749 float error = INFINITY;
752 dt_control_log(_(
"simple mixer mode requires normalized rows with non-zero sums."));
763 float error = INFINITY;
766 dt_control_log(_(
"primaries mixer mode requires a non-singular 3x3 matrix with non-zero affine sums."));
793 const int point = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(widget),
"split-point"));
795 = {
g->point[
point].simple_theta,
g->point[
point].simple_psi,
g->point[
point].simple_stretch_1,
796 g->point[
point].simple_stretch_2,
g->point[
point].simple_coupling_1,
797 g->point[
point].simple_coupling_2 };
799 float M[3][3] = { { 0.f } };
822 const int point = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(widget),
"split-point"));
824 = {
g->point[
point].primaries_achromatic_hue,
g->point[
point].primaries_achromatic_purity,
825 g->point[
point].primaries_red_hue,
g->point[
point].primaries_red_purity,
826 g->point[
point].primaries_green_hue,
g->point[
point].primaries_green_purity,
827 g->point[
point].primaries_blue_hue,
g->point[
point].primaries_blue_purity,
828 g->point[
point].primaries_gain };
830 float M[3][3] = { { 0.f } };
835 dt_control_log(_(
"primaries mixer mode requires a non-singular 3x3 matrix with non-zero affine sums."));
870 for(
int i = 0;
i < 3;
i++)
d->rgb_to_xyz_transposed[
i][
i] = 1.f;
884 if(
d->bright_luminance <=
d->dark_luminance)
885 d->bright_luminance =
d->dark_luminance + fmaxf(
d->dark_luminance * 0.01f, 1e-4f);
902 const void *
const restrict ivoid,
void *
const restrict
ovoid)
905 const float *
const restrict in = (
const float *
const restrict)ivoid;
906 float *
const restrict
out = (
float *
const restrict)
ovoid;
911 for(
size_t k = 0;
k < pixels * 4;
k += 4)
916 const dt_aligned_pixel_simd_t input_v = dt_load_simd_aligned(input);
919 dt_mat3x4_mul_vec4(input_v, dt_colormatrix_row_to_simd(
d->rgb_to_xyz_transposed, 0),
920 dt_colormatrix_row_to_simd(
d->rgb_to_xyz_transposed, 1),
921 dt_colormatrix_row_to_simd(
d->rgb_to_xyz_transposed, 2)));
923 _get_split_matrix(fmaxf(
XYZ[1], 0.f),
d, combined_matrix);
926 dt_colormatrix_row_to_simd(combined_matrix, 0),
927 dt_colormatrix_row_to_simd(combined_matrix, 1),
928 dt_colormatrix_row_to_simd(combined_matrix, 2)));
929 out[
k + 3] = input[3];
938 cl_mem dev_in, cl_mem dev_out)
945 const int devid = pipe->
devid;
950 cl_mem rgb_to_xyz_cl = NULL;
951 cl_mem dark_matrix_cl = NULL;
952 cl_mem bright_matrix_cl = NULL;
973 if(err != CL_SUCCESS)
goto error;
990 const int program = 32;
1024 const dt_iop_module_t *
const sampled_module = piece && piece->module ? piece->module : self;
1037 if(
point < 0)
return;
1042 work_profile->unbounded_coeffs_in,
1068 float simple_error = INFINITY;
1069 float primaries_error = INFINITY;
1088 if(
g->preview_surface)
1090 cairo_surface_destroy(
g->preview_surface);
1091 g->preview_surface = NULL;
1093 g->preview_width = 0;
1094 g->preview_height = 0;
1100 g_object_set_data(G_OBJECT(widget),
"split-point", GINT_TO_POINTER(
point));
1106 static const char *
const row_label[3] = { N_(
"output red"), N_(
"output green"), N_(
"output blue") };
1107 static const char *
const input_label[3] = { N_(
"input R"), N_(
"input G"), N_(
"input B") };
1114 for(
int col = 0; col < 3; col++)
1125 g->point[
point].normalize[
row] = gtk_check_button_new_with_label(_(
"normalize"));
1135 g->point[
point].simple_theta
1141 g->point[
point].simple_psi
1147 g->point[
point].simple_stretch_1
1151 g->point[
point].simple_stretch_2
1155 g->point[
point].simple_coupling_2
1161 g->point[
point].simple_coupling_1
1166 g->point[
point].simple_theta,
1168 g->point[
point].simple_psi,
1169 g->point[
point].simple_stretch_1,
1170 g->point[
point].simple_stretch_2,
1172 g->point[
point].simple_coupling_2,
1173 g->point[
point].simple_coupling_1,
1176 for(
size_t i = 0;
i < G_N_ELEMENTS(widgets);
i++)
1178 if(
i != 1 &&
i != 5)
1190 g->point[
point].primaries_achromatic_hue
1196 g->point[
point].primaries_achromatic_purity
1200 g->point[
point].primaries_red_hue
1206 g->point[
point].primaries_red_purity
1210 g->point[
point].primaries_green_hue
1216 g->point[
point].primaries_green_purity
1220 g->point[
point].primaries_blue_hue
1226 g->point[
point].primaries_blue_purity
1230 g->point[
point].primaries_gain
1236 g->point[
point].primaries_achromatic_hue,
1237 g->point[
point].primaries_achromatic_purity,
1239 g->point[
point].primaries_red_hue,
1240 g->point[
point].primaries_red_purity,
1242 g->point[
point].primaries_green_hue,
1243 g->point[
point].primaries_green_purity,
1245 g->point[
point].primaries_blue_hue,
1246 g->point[
point].primaries_blue_purity,
1248 g->point[
point].primaries_gain,
1251 for(
size_t i = 0;
i < G_N_ELEMENTS(widgets);
i++)
1266 g->preview_surface = NULL;
1267 g->preview_width = 0;
1268 g->preview_height = 0;
1270 g->preview = GTK_WIDGET(gtk_drawing_area_new());
1272 g_signal_connect(G_OBJECT(
g->preview),
"draw", G_CALLBACK(
_preview_draw), self);
1276 gtk_box_pack_start(GTK_BOX(self->
widget), GTK_WIDGET(
g->tabs),
FALSE,
FALSE, 0);
1281 g->point[
point].page = page;
1286 point == 0 ? -16.f : 0.f, 2));
1289 gtk_widget_set_tooltip_text(
g->point[
point].ev, _(
"sample average luminance from an area to set this keyframe"));
1294 g->point[
point].temperature
1300 g_signal_connect(G_OBJECT(
g->point[
point].temperature),
"value-changed", G_CALLBACK(
_general_callback), self);
1301 gtk_box_pack_start(GTK_BOX(page),
g->point[
point].temperature,
FALSE,
FALSE, 0);
1310 gtk_box_pack_start(GTK_BOX(page),
g->point[
point].mixer_mode,
FALSE,
FALSE, 0);
1312 g->point[
point].mixer_stack = gtk_stack_new();
1313 gtk_stack_set_hhomogeneous(GTK_STACK(
g->point[
point].mixer_stack),
FALSE);
1314 gtk_stack_set_vhomogeneous(GTK_STACK(
g->point[
point].mixer_stack),
FALSE);
1315 gtk_stack_set_transition_type(GTK_STACK(
g->point[
point].mixer_stack), GTK_STACK_TRANSITION_TYPE_NONE);
1316 gtk_box_pack_start(GTK_BOX(page),
g->point[
point].mixer_stack,
FALSE,
FALSE, 0);
1321 gtk_stack_add_named(GTK_STACK(
g->point[
point].mixer_stack), complete,
"complete");
1322 gtk_stack_add_named(GTK_STACK(
g->point[
point].mixer_stack), simple,
"simple");
1323 gtk_stack_add_named(GTK_STACK(
g->point[
point].mixer_stack), primaries,
"primaries");
1342 if(
g->preview_surface) cairo_surface_destroy(
g->preview_surface);
1351 memset(
d, 0,
sizeof(*
d));
1367 module->default_enabled = FALSE;
static void error(char *msg)
uint32_t container(dt_lib_module_t *self)
void dt_bauhaus_slider_set_soft_range(GtkWidget *widget, float soft_min, float soft_max)
float dt_bauhaus_slider_get(GtkWidget *widget)
int dt_bauhaus_combobox_get(GtkWidget *widget)
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)
GtkWidget * dt_bauhaus_slider_new_with_range(dt_bauhaus_t *bh, dt_gui_module_t *self, float min, float max, float step, float defval, int digits)
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_bauhaus_combobox_add(GtkWidget *widget, const char *text)
void dt_bauhaus_slider_set_factor(GtkWidget *widget, float factor)
static __DT_CLONE_TARGETS__ void normalize(float *const buffer, const size_t width, const size_t height, const float norm)
void dt_iop_channelmixer_shared_paint_row_sliders(dt_adaptation_t adaptation, const dt_iop_order_iccprofile_info_t *const work_profile, const dt_iop_order_iccprofile_info_t *const display_profile, const float r, const float g, const float b, const gboolean normalize, const float row[3], GtkWidget *const widgets[3])
void dt_iop_channelmixer_shared_paint_primaries_sliders(const dt_adaptation_t adaptation, const dt_iop_order_iccprofile_info_t *const work_profile, const dt_iop_order_iccprofile_info_t *const display_profile, const dt_iop_channelmixer_shared_primaries_basis_t basis, const dt_iop_channelmixer_shared_primaries_params_t *const primaries, GtkWidget *const widgets[9])
void dt_iop_channelmixer_shared_simple_from_sliders(GtkWidget *const widgets[6], dt_iop_channelmixer_shared_simple_params_t *simple)
void dt_iop_channelmixer_shared_paint_temperature_slider(GtkWidget *const widget, const float temperature_min, const float temperature_max)
void dt_iop_channelmixer_shared_primaries_to_sliders(const dt_iop_channelmixer_shared_primaries_params_t *const primaries, GtkWidget *const widgets[9])
void dt_iop_channelmixer_shared_simple_to_matrix(const dt_iop_channelmixer_shared_simple_params_t *const simple, float M[3][3])
void dt_iop_channelmixer_shared_simple_to_sliders(const dt_iop_channelmixer_shared_simple_params_t *const simple, GtkWidget *const widgets[6])
void dt_iop_channelmixer_shared_work_rgb_to_display(const dt_aligned_pixel_t work_rgb, const dt_iop_order_iccprofile_info_t *const work_profile, const dt_iop_order_iccprofile_info_t *const display_profile, dt_aligned_pixel_t display_rgb)
void dt_iop_channelmixer_shared_paint_simple_sliders(const dt_adaptation_t adaptation, const dt_iop_order_iccprofile_info_t *const work_profile, const dt_iop_order_iccprofile_info_t *const display_profile, const dt_iop_channelmixer_shared_simple_params_t *const simple, GtkWidget *const widgets[6])
gboolean dt_iop_channelmixer_shared_primaries_from_matrix(const dt_iop_channelmixer_shared_primaries_basis_t basis, const float M[3][3], dt_iop_channelmixer_shared_primaries_params_t *primaries)
void dt_iop_channelmixer_shared_simple_from_matrix(const float M[3][3], dt_iop_channelmixer_shared_simple_params_t *simple)
void dt_iop_channelmixer_shared_mul3x3(const float A[3][3], const float B[3][3], float C[3][3])
gboolean dt_iop_channelmixer_shared_rows_are_normalized(const gboolean normalize[3])
float dt_iop_channelmixer_shared_roundtrip_error(const float M[3][3], const float roundtrip[3][3])
gboolean dt_iop_channelmixer_shared_get_matrix(const float rows[3][3], const gboolean normalize[3], const gboolean force_normalize, float M[3][3])
gboolean dt_iop_channelmixer_shared_primaries_to_matrix(const dt_iop_channelmixer_shared_primaries_basis_t basis, const dt_iop_channelmixer_shared_primaries_params_t *primaries, float M[3][3])
void dt_iop_channelmixer_shared_primaries_from_sliders(GtkWidget *const widgets[9], dt_iop_channelmixer_shared_primaries_params_t *primaries)
#define DT_IOP_CHANNELMIXER_SHARED_SIMPLE_EPS
@ DT_IOP_CHANNELMIXER_SHARED_PRIMARIES_BASIS_RGB
static const dt_aligned_pixel_simd_t const dt_adaptation_t const float p
static float dt_camera_rgb_luminance(const float4 rgb)
GtkWidget * dt_color_picker_new(dt_iop_module_t *module, dt_iop_color_picker_kind_t kind, GtkWidget *w)
dt_apply_transposed_color_matrix(XYZ, xyz_to_srgb_matrix_transposed, sRGB)
static dt_aligned_pixel_t XYZ
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)))
const dt_colormatrix_t matrix
static const dt_colormatrix_t M
int dt_conf_key_exists(const char *key)
void dt_conf_set_int(const char *name, int val)
int dt_conf_get_int(const char *name)
void dt_control_log(const char *msg,...)
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__(...)
#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)
GtkWidget * dt_ui_notebook_page(GtkNotebook *notebook, const char *text, const char *tooltip)
GtkNotebook * dt_ui_notebook_new()
static cairo_surface_t * dt_cairo_image_surface_create(cairo_format_t format, int width, int height)
static GtkWidget * dt_ui_section_label_new(const gchar *str)
static int dt_cairo_image_surface_get_width(cairo_surface_t *surface)
#define DT_GUI_BOX_SPACING
#define DT_PIXEL_APPLY_DPI(value)
static int dt_cairo_image_surface_get_height(cairo_surface_t *surface)
static void illuminant_xy_to_XYZ(const float x, const float y, dt_aligned_pixel_t XYZ)
static void CCT_to_xy_daylight(const float t, float *x, float *y)
static void CCT_to_xy_blackbody(const float t, float *x, float *y)
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)
#define dt_omploop_sfence()
@ IOP_FLAGS_INCLUDE_IN_STYLES
@ IOP_FLAGS_SUPPORTS_BLENDING
#define IOP_GUI_ALLOC(module)
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_get_pipe_work_profile_info(const struct dt_dev_pixelpipe_t *pipe)
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)
dt_iop_order_iccprofile_info_t * dt_ioppr_get_iop_work_profile_info(struct dt_iop_module_t *module, GList *iop_list)
float *const restrict luminance
float *const restrict const size_t k
float DT_ALIGNED_ARRAY dt_colormatrix_t[4][4]
static void transpose_3xSSE(const dt_colormatrix_t input, dt_colormatrix_t output)
static void pack_3xSSE_to_3x4(const dt_colormatrix_t input, float output[12])
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)
#define DT_DEBUG_CONTROL_SIGNAL_DISCONNECT(ctlsig, cb, user_data)
@ DT_SIGNAL_DEVELOP_PREVIEW_PIPE_FINISHED
This signal is raised when develop preview pipe process is finished no param, no returned value.
@ DT_SIGNAL_DEVELOP_UI_PIPE_FINISHED
This signal is raised when pipe is finished and the gui is attached no param, no returned value.
#define DT_DEBUG_CONTROL_SIGNAL_CONNECT(ctlsig, signal, cb, user_data)
struct _GtkWidget GtkWidget
void init(dt_iop_module_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 restrict ivoid, void *const restrict ovoid)
static void _set_point_complete_widgets(dt_iop_splittoning_rgb_gui_data_t *g, const dt_iop_splittoning_rgb_params_t *p, const int point)
const char ** description(struct dt_iop_module_t *self)
static const char *const _mode_conf[2]
#define DT_SPLITTONING_RGB_PREVIEW_HEIGHT
static void _build_cat16_rgb_matrix(const dt_iop_order_iccprofile_info_t *work_profile, const float temperature, float CAT[3][3])
static void _set_point_rows(dt_iop_splittoning_rgb_params_t *p, const int point, const float M[3][3])
static void _queue_preview_redraw(dt_iop_module_t *self)
static gboolean _sync_simple_from_params(dt_iop_module_t *self, const int point, float *error)
static void _simple_slider_callback(GtkWidget *widget, gpointer user_data)
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 void _primaries_slider_callback(GtkWidget *widget, gpointer user_data)
static void _pipe_finished_callback(gpointer instance, gpointer user_data)
Refresh cached GUI colors after the darkroom pipe has converged.
static void _mixer_mode_callback(GtkWidget *widget, gpointer user_data)
static void _general_callback(GtkWidget *widget, gpointer user_data)
void init_pipe(struct dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
dt_iop_splittoning_rgb_point_t
@ DT_SPLITTONING_RGB_POINT_BRIGHT
@ DT_SPLITTONING_RGB_POINT_DARK
static void _update_point_slider_colors(dt_iop_module_t *self, int point)
Repaint every slider background for one split-toning keyframe.
static void _commit_gui_change(dt_iop_module_t *self, GtkWidget *changed)
static void _tag_widget(GtkWidget *widget, const int point)
void gui_update(struct dt_iop_module_t *self)
Refresh GUI controls from current params and configuration.
#define DT_SPLITTONING_RGB_ROW_COUNT
dt_iop_splittoning_rgb_mixer_mode_t
@ DT_SPLITTONING_RGB_MIXER_PRIMARIES
@ DT_SPLITTONING_RGB_MIXER_COMPLETE
@ DT_SPLITTONING_RGB_MIXER_SIMPLE
static gboolean _sync_primaries_from_params(dt_iop_module_t *self, const int point, float *error)
void gui_init(struct dt_iop_module_t *self)
static float _ev_to_grey(const float ev)
static float _ev_to_luminance(const float ev)
static int _build_point_transform(const dt_iop_splittoning_rgb_params_t *p, const int point, const dt_iop_order_iccprofile_info_t *work_profile, dt_colormatrix_t point_matrix)
#define DT_SPLITTONING_RGB_COMPLETE_COUNT
void cleanup_global(dt_iop_module_so_t *module)
static void _render_preview_surface(dt_iop_module_t *self, cairo_surface_t *surface)
Render the cached split-toning preview as a simple keyed gradient.
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 gboolean _preview_draw(GtkWidget *widget, cairo_t *cr, gpointer user_data)
void gui_cleanup(struct dt_iop_module_t *self)
static void _temperature_to_xy(const float temperature, float *x, float *y)
static void _get_point_rows(const dt_iop_splittoning_rgb_params_t *p, const int point, float rows[3][3], gboolean normalize[3])
static void _build_complete_ui(dt_iop_module_t *self, dt_iop_splittoning_rgb_gui_data_t *g, const int point, GtkWidget *container)
void cleanup_pipe(struct dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
void init_global(dt_iop_module_so_t *module)
static void _set_point_mixer_mode(dt_iop_splittoning_rgb_gui_data_t *g, const int point, const dt_iop_splittoning_rgb_mixer_mode_t mode)
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 void _update_point_gui(dt_iop_module_t *self, const int point, GtkWidget *changed)
static void _build_simple_ui(dt_iop_module_t *self, dt_iop_splittoning_rgb_gui_data_t *g, const int point, GtkWidget *container)
#define DT_SPLITTONING_RGB_POINT_COUNT
void color_picker_apply(dt_iop_module_t *self, GtkWidget *picker, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
Set a brightness keyframe from the average luminance of a picked area.
static const char *const _point_label[2]
static void _build_primaries_ui(dt_iop_module_t *self, dt_iop_splittoning_rgb_gui_data_t *g, const int point, GtkWidget *container)
const float uint32_t state[4]
struct dt_gui_gtk_t * gui
struct dt_control_signal_t * signals
struct dt_bauhaus_t * bauhaus
struct dt_develop_t * develop
struct dt_iop_module_t *void * data
struct dt_dev_pixelpipe_t * preview_pipe
struct dt_dev_pixelpipe_t * pipe
dt_iop_buffer_type_t datatype
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
dt_aligned_pixel_t picked_color
dt_colormatrix_t matrix_out_transposed
dt_colormatrix_t matrix_in_transposed
dt_colormatrix_t matrix_in
Region of interest passed through the pixelpipe.
dt_colormatrix_t rgb_to_xyz_transposed
float point_matrix_cl[2][12]
dt_colormatrix_t point_matrix[2]
int kernel_splittoningrgb
cairo_surface_t * preview_surface
GtkWidget * simple_stretch_2
GtkWidget * primaries_achromatic_hue
GtkWidget * primaries_blue_hue
GtkWidget * primaries_red_hue
GtkWidget * simple_stretch_1
GtkWidget * simple_coupling_2
GtkWidget * primaries_red_purity
GtkWidget * complete[3][3]
GtkWidget * primaries_green_purity
GtkWidget * simple_coupling_1
GtkWidget * primaries_gain
GtkWidget * primaries_achromatic_purity
GtkWidget * primaries_blue_purity
GtkWidget * primaries_green_hue