Ansel 0.0
A darktable fork - bloat + design vision
Loading...
Searching...
No Matches
splittoningrgb.c File Reference
#include "bauhaus/bauhaus.h"
#include "common/chromatic_adaptation.h"
#include "common/darktable.h"
#include "common/iop_profile.h"
#include "common/illuminants.h"
#include "common/matrices.h"
#include "common/opencl.h"
#include "control/control.h"
#include "develop/develop.h"
#include "develop/imageop.h"
#include "develop/imageop_gui.h"
#include "develop/imageop_math.h"
#include "develop/openmp_maths.h"
#include "gui/color_picker_proxy.h"
#include "gui/gtk.h"
#include "iop/channelmixerrgb_shared.h"
#include "iop/iop_api.h"
#include "channelmixerrgb_shared.c"
#include <gtk/gtk.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>
+ Include dependency graph for splittoningrgb.c:

Data Structures

struct  dt_iop_splittoning_rgb_params_t
 
struct  dt_iop_splittoning_rgb_data_t
 
struct  dt_iop_splittoning_rgb_global_data_t
 
struct  dt_iop_splittoning_rgb_point_gui_t
 
struct  dt_iop_splittoning_rgb_gui_data_t
 

Macros

#define DT_SPLITTONING_RGB_POINT_COUNT   2
 
#define DT_SPLITTONING_RGB_ROW_COUNT   3
 
#define DT_SPLITTONING_RGB_COMPLETE_COUNT   3
 
#define DT_SPLITTONING_RGB_PREVIEW_HEIGHT   60
 

Typedefs

typedef enum dt_iop_splittoning_rgb_point_t dt_iop_splittoning_rgb_point_t
 
typedef enum dt_iop_splittoning_rgb_mixer_mode_t dt_iop_splittoning_rgb_mixer_mode_t
 
typedef struct dt_iop_splittoning_rgb_params_t dt_iop_splittoning_rgb_params_t
 
typedef struct dt_iop_splittoning_rgb_data_t dt_iop_splittoning_rgb_data_t
 
typedef struct dt_iop_splittoning_rgb_global_data_t dt_iop_splittoning_rgb_global_data_t
 
typedef struct dt_iop_splittoning_rgb_point_gui_t dt_iop_splittoning_rgb_point_gui_t
 
typedef struct dt_iop_splittoning_rgb_gui_data_t dt_iop_splittoning_rgb_gui_data_t
 

Enumerations

enum  dt_iop_splittoning_rgb_point_t {
  DT_SPLITTONING_RGB_POINT_DARK = 0 ,
  DT_SPLITTONING_RGB_POINT_BRIGHT = 1
}
 
enum  dt_iop_splittoning_rgb_mixer_mode_t {
  DT_SPLITTONING_RGB_MIXER_COMPLETE = 0 ,
  DT_SPLITTONING_RGB_MIXER_SIMPLE = 1 ,
  DT_SPLITTONING_RGB_MIXER_PRIMARIES = 2
}
 

Functions

static void _update_point_slider_colors (dt_iop_module_t *self, const int point)
 Repaint every slider background for one split-toning keyframe.
 
const char * name ()
 
const char * aliases ()
 
const char ** description (struct dt_iop_module_t *self)
 
int default_group ()
 
int flags ()
 
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 float _ev_to_grey (const float ev)
 
static float _ev_to_luminance (const float ev)
 
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 _set_point_rows (dt_iop_splittoning_rgb_params_t *p, const int point, const float M[3][3])
 
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)
 
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)
 
static void _build_cat16_rgb_matrix (const dt_iop_order_iccprofile_info_t *work_profile, const float temperature, float CAT[3][3])
 
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)
 
static __attribute__ ((always_inline))
 Interpolate two keyed correction matrices entry-wise.
 
static gboolean _sync_simple_from_params (dt_iop_module_t *self, const int point, float *error)
 
static gboolean _sync_primaries_from_params (dt_iop_module_t *self, const int point, float *error)
 
static void _queue_preview_redraw (dt_iop_module_t *self)
 
static void _pipe_finished_callback (gpointer instance, gpointer user_data)
 Refresh cached GUI colors after the darkroom pipe has converged.
 
static void _update_point_gui (dt_iop_module_t *self, const int point, GtkWidget *changed)
 
static void _commit_gui_change (dt_iop_module_t *self, GtkWidget *changed)
 
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.
 
static gboolean _preview_draw (GtkWidget *widget, cairo_t *cr, gpointer user_data)
 
static void _general_callback (GtkWidget *widget, gpointer user_data)
 
static void _mixer_mode_callback (GtkWidget *widget, gpointer user_data)
 
static void _simple_slider_callback (GtkWidget *widget, gpointer user_data)
 
static void _primaries_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)
 
void init_pipe (struct dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
 
void cleanup_pipe (struct dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
 
__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)
 
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)
 
void init_global (dt_iop_module_so_t *module)
 
void cleanup_global (dt_iop_module_so_t *module)
 
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.
 
void gui_update (struct dt_iop_module_t *self)
 Refresh GUI controls from current params and configuration.
 
static void _tag_widget (GtkWidget *widget, const int point)
 
static void _build_complete_ui (dt_iop_module_t *self, dt_iop_splittoning_rgb_gui_data_t *g, const int point, GtkWidget *container)
 
static void _build_simple_ui (dt_iop_module_t *self, dt_iop_splittoning_rgb_gui_data_t *g, const int point, GtkWidget *container)
 
static void _build_primaries_ui (dt_iop_module_t *self, dt_iop_splittoning_rgb_gui_data_t *g, const int point, GtkWidget *container)
 
void gui_init (struct dt_iop_module_t *self)
 
void gui_cleanup (struct dt_iop_module_t *self)
 
void init (dt_iop_module_t *module)
 

Variables

static const char *const _mode_conf [2]
 
static const char *const _point_label [2]
 

Macro Definition Documentation

◆ DT_SPLITTONING_RGB_COMPLETE_COUNT

#define DT_SPLITTONING_RGB_COMPLETE_COUNT   3

◆ DT_SPLITTONING_RGB_POINT_COUNT

#define DT_SPLITTONING_RGB_POINT_COUNT   2

◆ DT_SPLITTONING_RGB_PREVIEW_HEIGHT

#define DT_SPLITTONING_RGB_PREVIEW_HEIGHT   60

◆ DT_SPLITTONING_RGB_ROW_COUNT

#define DT_SPLITTONING_RGB_ROW_COUNT   3

Typedef Documentation

◆ dt_iop_splittoning_rgb_data_t

◆ dt_iop_splittoning_rgb_global_data_t

◆ dt_iop_splittoning_rgb_gui_data_t

◆ dt_iop_splittoning_rgb_mixer_mode_t

◆ dt_iop_splittoning_rgb_params_t

◆ dt_iop_splittoning_rgb_point_gui_t

◆ dt_iop_splittoning_rgb_point_t

Enumeration Type Documentation

◆ dt_iop_splittoning_rgb_mixer_mode_t

Enumerator
DT_SPLITTONING_RGB_MIXER_COMPLETE 
DT_SPLITTONING_RGB_MIXER_SIMPLE 
DT_SPLITTONING_RGB_MIXER_PRIMARIES 

◆ dt_iop_splittoning_rgb_point_t

Enumerator
DT_SPLITTONING_RGB_POINT_DARK 
DT_SPLITTONING_RGB_POINT_BRIGHT 

Function Documentation

◆ __attribute__()

static __attribute__ ( (always_inline)  )
inlinestatic

Interpolate two keyed correction matrices entry-wise.

Build the keyed full transform matrix for one scene luminance.

The transforms are stored in transposed padded form so they can be fed directly to the SIMD matrix-vector multiply. Interpolating them entry-wise in that storage remains equivalent to interpolating the underlying 3x3 matrix.

Parameters
[in]fromSource keyed correction matrix in transposed padded form.
[in]toDestination keyed correction matrix in transposed padded form.
[in]alphaInterpolation factor from source to destination.
[out]interpolatedInterpolated matrix in the same transposed padded form.

Inside the [dark ; bright] segment, the module linearly interpolates between the two user transforms. Outside that segment, the nearest transform fades linearly back to identity over one segment length so the correction tapers out instead of clipping.

Parameters
[in]luminanceCurrent pixel scene luminance in XYZ Y.
[in]dPrecomputed module state for the current pipe.
[out]matrixKeyed full transform matrix in transposed padded form.

References row.

◆ _build_cat16_rgb_matrix()

◆ _build_complete_ui()

◆ _build_point_transform()

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 
)
static

◆ _build_primaries_ui()

◆ _build_simple_ui()

◆ _commit_gui_change()

◆ _ev_to_grey()

static float _ev_to_grey ( const float  ev)
inlinestatic

Referenced by _ev_to_luminance().

◆ _ev_to_luminance()

static float _ev_to_luminance ( const float  ev)
inlinestatic

References _ev_to_grey().

Referenced by _render_preview_surface(), and commit_params().

◆ _general_callback()

◆ _get_point_rows()

static void _get_point_rows ( const dt_iop_splittoning_rgb_params_t p,
const int  point,
float  rows[3][3],
gboolean  normalize[3] 
)
static

◆ _mixer_mode_callback()

◆ _pipe_finished_callback()

static void _pipe_finished_callback ( gpointer  instance,
gpointer  user_data 
)
static

Refresh cached GUI colors after the darkroom pipe has converged.

Slider backgrounds and the preview gradient depend on the current work and display profiles. Those profiles may be unavailable during the very first draw after the module widget is created, so we listen to pipe completion and rebuild the cached surfaces as soon as the pipe is ready.

Parameters
[in]instanceUnused signal emitter.
[in]user_dataCurrent module instance.

References _queue_preview_redraw(), _update_point_slider_colors(), DT_SPLITTONING_RGB_POINT_COUNT, g, dt_iop_module_t::gui_data, and IS_NULL_PTR.

Referenced by gui_cleanup(), and gui_init().

◆ _preview_draw()

static gboolean _preview_draw ( GtkWidget widget,
cairo_t *  cr,
gpointer  user_data 
)
static

◆ _primaries_slider_callback()

◆ _queue_preview_redraw()

static void _queue_preview_redraw ( dt_iop_module_t self)
static

◆ _render_preview_surface()

static void _render_preview_surface ( dt_iop_module_t self,
cairo_surface_t *  surface 
)
static

Render the cached split-toning preview as a simple keyed gradient.

The drawing area is meant as a direct preview of the keyed blend, not as a plotting canvas. We therefore sweep a neutral grey ramp once, cache the resulting Cairo image surface and only rebuild it when parameters change or the widget size changes.

Parameters
[in]selfCurrent module instance.
[in,out]surfaceCached Cairo image surface to repaint.

References _build_point_transform(), _ev_to_luminance(), dt_iop_module_t::dev, dt_apply_transposed_color_matrix(), dt_iop_channelmixer_shared_work_rgb_to_display(), dt_ioppr_get_pipe_output_profile_info(), dt_ioppr_get_pipe_work_profile_info(), DT_SPLITTONING_RGB_POINT_BRIGHT, DT_SPLITTONING_RGB_POINT_DARK, dt_store_simd_aligned(), height, i, IS_NULL_PTR, dt_iop_order_iccprofile_info_t::matrix_in_transposed, p, dt_iop_module_t::params, dt_develop_t::preview_pipe, state, width, x, and XYZ.

Referenced by _preview_draw().

◆ _set_point_complete_widgets()

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 
)
static

◆ _set_point_mixer_mode()

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 
)
static

◆ _set_point_rows()

static void _set_point_rows ( dt_iop_splittoning_rgb_params_t p,
const int  point,
const float  M[3][3] 
)
static

References M, and p.

Referenced by _primaries_slider_callback(), and _simple_slider_callback().

◆ _simple_slider_callback()

◆ _sync_primaries_from_params()

◆ _sync_simple_from_params()

◆ _tag_widget()

static void _tag_widget ( GtkWidget widget,
const int  point 
)
static

◆ _temperature_to_xy()

static void _temperature_to_xy ( const float  temperature,
float *  x,
float *  y 
)
static

◆ _update_point_gui()

◆ _update_point_slider_colors()

static void _update_point_slider_colors ( dt_iop_module_t self,
const int  point 
)
static

Repaint every slider background for one split-toning keyframe.

The complete, simple and primaries controls all act on the same effective mixer, just viewed through different parameterizations. We therefore refresh every slider tint from the current widget state after each edit so the GUI keeps reflecting the exact correction the user is shaping.

Parameters
[in]selfCurrent module instance.
[in]pointShadow or highlight keyframe being edited.

References dt_iop_module_t::dev, DT_ADAPTATION_RGB, dt_iop_channelmixer_shared_paint_primaries_sliders(), dt_iop_channelmixer_shared_paint_row_sliders(), dt_iop_channelmixer_shared_paint_simple_sliders(), dt_iop_channelmixer_shared_paint_temperature_slider(), DT_IOP_CHANNELMIXER_SHARED_PRIMARIES_BASIS_RGB, dt_iop_channelmixer_shared_primaries_from_sliders(), dt_iop_channelmixer_shared_simple_from_sliders(), dt_ioppr_get_pipe_output_profile_info(), dt_ioppr_get_pipe_work_profile_info(), g, dt_iop_module_t::gui_data, p, dt_iop_module_t::params, dt_develop_t::pipe, and row.

Referenced by _commit_gui_change(), _pipe_finished_callback(), and gui_update().

◆ aliases()

const char * aliases ( )

◆ cleanup_global()

◆ cleanup_pipe()

void cleanup_pipe ( struct dt_iop_module_t self,
dt_dev_pixelpipe_t pipe,
dt_dev_pixelpipe_iop_t piece 
)

◆ color_picker_apply()

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.

The picker samples the current module buffer in working RGB. We convert that average RGB to scene luminance Y in the active working profile, then map the result to EV so each anchor can be snapped directly to image content.

Parameters
[in]selfCurrent module instance.
[in]pickerPicker-enabled brightness slider that requested the sample.
[in]pipeActive pixelpipe that produced the sampled buffer.
[in]pieceCurrent module instance on that pipe.

References _commit_gui_change(), darktable, dt_iop_module_t::dev, dt_bauhaus_slider_set(), dt_camera_rgb_luminance(), dt_ioppr_get_iop_work_profile_info(), dt_ioppr_get_pipe_current_profile_info(), DT_SPLITTONING_RGB_POINT_BRIGHT, DT_SPLITTONING_RGB_POINT_DARK, g, darktable_t::gui, dt_iop_module_t::gui_data, dt_develop_t::iop, IS_NULL_PTR, luminance, dt_iop_order_iccprofile_info_t::lut_in, dt_iop_order_iccprofile_info_t::lutsize, dt_iop_order_iccprofile_info_t::matrix_in, dt_iop_order_iccprofile_info_t::nonlinearlut, NORM_MIN, p, dt_iop_module_t::params, dt_iop_module_t::picked_color, dt_iop_module_t::picked_color_max, dt_iop_module_t::picked_color_min, and dt_gui_gtk_t::reset.

◆ commit_params()

◆ default_colorspace()

int default_colorspace ( dt_iop_module_t self,
dt_dev_pixelpipe_t pipe,
const dt_dev_pixelpipe_iop_t piece 
)

References IOP_CS_RGB.

◆ default_group()

int default_group ( )

References IOP_GROUP_COLOR.

◆ description()

const char ** description ( struct dt_iop_module_t self)

◆ flags()

◆ gui_cleanup()

◆ gui_init()

◆ gui_update()

◆ init()

◆ init_global()

◆ init_pipe()

◆ input_format()

◆ name()

const char * name ( )

◆ process()

◆ process_cl()

Variable Documentation

◆ _mode_conf

const char* const _mode_conf[2]
static
Initial value:
= {
"plugins/darkroom/splittoningrgb/dark_mixer_mode",
"plugins/darkroom/splittoningrgb/bright_mixer_mode"
}

Referenced by _mixer_mode_callback(), _update_point_gui(), and gui_update().

◆ _point_label

const char* const _point_label[2]
static
Initial value:
= {
N_("dark"),
}

Referenced by gui_init().