Ansel 0.0
A darktable fork - bloat + design vision
Loading...
Searching...
No Matches
filmic.c File Reference
#include "bauhaus/bauhaus.h"
#include "common/colorspaces_inline_conversions.h"
#include "common/darktable.h"
#include "common/math.h"
#include "common/opencl.h"
#include "control/control.h"
#include "develop/develop.h"
#include "develop/imageop_math.h"
#include "dtgtk/button.h"
#include "dtgtk/drawingarea.h"
#include "dtgtk/expander.h"
#include "dtgtk/paint.h"
#include "gui/gtk.h"
#include "gui/presets.h"
#include "gui/color_picker_proxy.h"
#include "iop/iop_api.h"
#include "develop/imageop.h"
#include "gui/draw.h"
#include <assert.h>
#include <stdlib.h>
#include <string.h>
+ Include dependency graph for filmic.c:

Data Structures

struct  dt_iop_filmic_params_t
 
struct  dt_iop_filmic_gui_data_t
 
struct  dt_iop_filmic_data_t
 
struct  dt_iop_filmic_nodes_t
 
struct  dt_iop_filmic_global_data_t
 

Macros

#define DT_GUI_CURVE_EDITOR_INSET   DT_PIXEL_APPLY_DPI(1)
 

Typedefs

typedef struct dt_iop_filmic_params_t dt_iop_filmic_params_t
 
typedef struct dt_iop_filmic_gui_data_t dt_iop_filmic_gui_data_t
 
typedef struct dt_iop_filmic_data_t dt_iop_filmic_data_t
 
typedef struct dt_iop_filmic_nodes_t dt_iop_filmic_nodes_t
 
typedef struct dt_iop_filmic_global_data_t dt_iop_filmic_global_data_t
 

Functions

const char * name ()
 
int default_group ()
 
int flags ()
 
const char * deprecated_msg ()
 
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)
 
int legacy_params (dt_iop_module_t *self, const void *const old_params, const int old_version, void *new_params, const int new_version)
 
void init_presets (dt_iop_module_so_t *self)
 
static float gaussian (float x, float std)
 
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 sanitize_latitude (dt_iop_filmic_params_t *p, dt_iop_filmic_gui_data_t *g)
 
static void apply_auto_grey (dt_iop_module_t *self)
 
static void apply_auto_black (dt_iop_module_t *self)
 
static void apply_auto_white_point_source (dt_iop_module_t *self)
 
static void security_threshold_callback (GtkWidget *slider, gpointer user_data)
 
static void apply_autotune (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)
 
static void grey_point_source_callback (GtkWidget *slider, gpointer user_data)
 
static void white_point_source_callback (GtkWidget *slider, gpointer user_data)
 
static void black_point_source_callback (GtkWidget *slider, gpointer user_data)
 
static void grey_point_target_callback (GtkWidget *slider, gpointer user_data)
 
static void latitude_stops_callback (GtkWidget *slider, gpointer user_data)
 
static void contrast_callback (GtkWidget *slider, gpointer user_data)
 
static void saturation_callback (GtkWidget *slider, gpointer user_data)
 
static void global_saturation_callback (GtkWidget *slider, gpointer user_data)
 
static void white_point_target_callback (GtkWidget *slider, gpointer user_data)
 
static void black_point_target_callback (GtkWidget *slider, gpointer user_data)
 
static void output_power_callback (GtkWidget *slider, gpointer user_data)
 
static void balance_callback (GtkWidget *slider, gpointer user_data)
 
static void interpolator_callback (GtkWidget *widget, dt_iop_module_t *self)
 
static void preserve_color_callback (GtkWidget *widget, dt_iop_module_t *self)
 
void compute_curve_lut (dt_iop_filmic_params_t *p, float *table, float *table_temp, int res, dt_iop_filmic_data_t *d, dt_iop_filmic_nodes_t *nodes_data)
 
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 init_pipe (dt_iop_module_t *self, 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)
 
void gui_update (dt_iop_module_t *self)
 Refresh GUI controls from current params and configuration.
 
void init (dt_iop_module_t *module)
 
void init_global (dt_iop_module_so_t *module)
 
void cleanup (dt_iop_module_t *module)
 
void cleanup_global (dt_iop_module_so_t *module)
 
void gui_reset (dt_iop_module_t *self)
 
static gboolean dt_iop_tonecurve_draw (GtkWidget *widget, cairo_t *crf, gpointer user_data)
 
static void _extra_options_button_changed (GtkDarktableToggleButton *widget, gpointer user_data)
 
void gui_init (dt_iop_module_t *self)
 

Macro Definition Documentation

◆ DT_GUI_CURVE_EDITOR_INSET

#define DT_GUI_CURVE_EDITOR_INSET   DT_PIXEL_APPLY_DPI(1)

Typedef Documentation

◆ dt_iop_filmic_data_t

◆ dt_iop_filmic_global_data_t

◆ dt_iop_filmic_gui_data_t

◆ dt_iop_filmic_nodes_t

◆ dt_iop_filmic_params_t

DOCUMENTATION

This code ports :

  1. Troy Sobotka's filmic curves for Blender (and other softs) https://github.com/sobotka/OpenAgX/blob/master/lib/agx_colour.py
  2. ACES camera logarithmic encoding https://github.com/ampas/aces-dev/blob/master/transforms/ctl/utilities/ACESutil.Lin_to_Log2_param.ctl

The ACES log implementation is taken from the profile_gamma.c IOP where it works in camera RGB space. Here, it works on an arbitrary RGB space. ProPhotoRGB has been chosen for its wide gamut coverage and for conveniency because it's already in darktable's libs. Any other RGB working space could work. This chouice could (should) also be exposed to the user.

The filmic curves are tonecurves intended to simulate the luminance transfer function of film with "S" curves. These could be reproduced in the tonecurve.c IOP, however what we offer here is a parametric interface useful to remap accurately and promptly the middle grey to any arbitrary value chosen accordingly to the destination space.

The combined use of both define a modern way to deal with large dynamic range photographs by remapping the values with a comprehensive interface avoiding many of the back and forth adjustments darktable is prone to enforce.

Function Documentation

◆ _extra_options_button_changed()

◆ apply_auto_black()

◆ apply_auto_grey()

◆ apply_auto_white_point_source()

◆ apply_autotune()

◆ balance_callback()

◆ black_point_source_callback()

◆ black_point_target_callback()

◆ cleanup()

◆ cleanup_global()

◆ cleanup_pipe()

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

◆ color_picker_apply()

◆ commit_params()

void commit_params ( dt_iop_module_t self,
dt_iop_params_t p1,
dt_dev_pixelpipe_t pipe,
dt_dev_pixelpipe_iop_t piece 
)

◆ compute_curve_lut()

void compute_curve_lut ( dt_iop_filmic_params_t p,
float *  table,
float *  table_temp,
int  res,
dt_iop_filmic_data_t d,
dt_iop_filmic_nodes_t nodes_data 
)

Now we have 3 segments :

  • x = [0.0 ; toe_log], curved part
  • x = [toe_log ; grey_log ; shoulder_log], linear part
  • x = [shoulder_log ; 1.0] curved part

BUT : in case some nodes overlap, we need to remove them to avoid degenerating of the curve

References coeff, CUBIC_SPLINE, d, dt_draw_curve_add_point(), dt_draw_curve_calc_values(), dt_draw_curve_destroy(), dt_draw_curve_new(), FALSE, MONOTONE_HERMITE, dt_iop_filmic_nodes_t::nodes, p, TRUE, dt_iop_filmic_nodes_t::x, and dt_iop_filmic_nodes_t::y.

Referenced by commit_params(), and dt_iop_tonecurve_draw().

◆ contrast_callback()

◆ 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_LAB.

◆ default_group()

int default_group ( )

References IOP_GROUP_TONES.

◆ deprecated_msg()

const char * deprecated_msg ( )

◆ dt_iop_tonecurve_draw()

◆ flags()

◆ gaussian()

static float gaussian ( float  x,
float  std 
)
inlinestatic

References M_PI, and x.

◆ global_saturation_callback()

static void global_saturation_callback ( GtkWidget slider,
gpointer  user_data 
)
static

◆ grey_point_source_callback()

◆ grey_point_target_callback()

◆ gui_init()

◆ gui_reset()

◆ gui_update()

void gui_update ( dt_iop_module_t self)

◆ init()

◆ init_global()

◆ init_pipe()

◆ init_presets()

◆ input_format()

◆ interpolator_callback()

◆ latitude_stops_callback()

◆ legacy_params()

int legacy_params ( dt_iop_module_t self,
const void *const  old_params,
const int  old_version,
void new_params,
const int  new_version 
)

References d, dt_iop_module_t::default_params, and n.

◆ name()

const char * name ( )

◆ output_power_callback()

◆ preserve_color_callback()

static void preserve_color_callback ( GtkWidget widget,
dt_iop_module_t self 
)
static

◆ process()

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 
)

The log2(x) -> -INF when x -> 0 thus very low values (noise) will get even lower, resulting in noise negative amplification, which leads to pepper noise in shadows. To avoid that, we need to clip values that are noise for sure. Using 16 bits RAW data, the black value (known by rawspeed for every manufacturer) could be used as a threshold. However, at this point of the pixelpipe, the RAW levels have already been corrected and everything can happen with black levels in the exposure module. So we define the threshold as the first non-null 16 bit integer

References dt_iop_filmic_data_t::black_source, c, dt_dev_pixelpipe_iop_t::data, DT_ALIGNED_ARRAY, DT_DEV_PIXELPIPE_DISPLAY_MASK, dt_iop_alpha_copy(), dt_Lab_to_XYZ(), dt_prophotorgb_to_XYZ(), dt_XYZ_to_prophotorgb(), dt_iop_filmic_data_t::dynamic_range, FALSE, fastlog2(), dt_iop_filmic_data_t::global_saturation, dt_iop_filmic_data_t::grad_2, dt_iop_filmic_data_t::grey_source, dt_iop_roi_t::height, dt_dev_pixelpipe_t::mask_display, max, out, dt_iop_filmic_data_t::output_power, dt_iop_filmic_data_t::preserve_color, rgb, dt_dev_pixelpipe_iop_t::roi_out, dt_iop_filmic_data_t::table, TRUE, dt_iop_roi_t::width, and XYZ.

◆ sanitize_latitude()

◆ saturation_callback()

static void saturation_callback ( GtkWidget slider,
gpointer  user_data 
)
static

◆ security_threshold_callback()

◆ white_point_source_callback()

◆ white_point_target_callback()