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, 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)
 
void init_presets (dt_iop_module_so_t *self)
 
static float gaussian (float x, float std)
 
void process (dt_iop_module_t *self, dt_dev_pixelpipe_iop_t *piece, const void *const ivoid, void *const ovoid, const dt_iop_roi_t *const roi_in, const dt_iop_roi_t *const roi_out)
 
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_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)
 
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()

static void black_point_target_callback ( GtkWidget *  slider,
gpointer  user_data 
)
static

◆ 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()

◆ 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 CUBIC_SPLINE, dt_draw_curve_add_point(), dt_draw_curve_calc_values(), dt_draw_curve_destroy(), dt_draw_curve_new(), FALSE, dt_iop_filmic_data_t::latitude_max, dt_iop_filmic_data_t::latitude_min, MONOTONE_HERMITE, dt_iop_filmic_nodes_t::nodes, 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()

static void contrast_callback ( GtkWidget *  slider,
gpointer  user_data 
)
static

◆ default_colorspace()

int default_colorspace ( dt_iop_module_t self,
dt_dev_pixelpipe_t pipe,
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.

◆ global_saturation_callback()

static void global_saturation_callback ( GtkWidget *  slider,
gpointer  user_data 
)
static

◆ grey_point_source_callback()

◆ grey_point_target_callback()

static void grey_point_target_callback ( GtkWidget *  slider,
gpointer  user_data 
)
static

◆ gui_init()

◆ gui_reset()

◆ gui_update()

◆ init()

◆ init_global()

◆ init_pipe()

◆ init_presets()

◆ interpolator_callback()

◆ latitude_stops_callback()

◆ legacy_params()

◆ name()

const char * name ( )

◆ output_power_callback()

static void output_power_callback ( GtkWidget *  slider,
gpointer  user_data 
)
static

◆ preserve_color_callback()

static void preserve_color_callback ( GtkWidget *  widget,
dt_iop_module_t self 
)
static

◆ process()

void process ( dt_iop_module_t self,
dt_dev_pixelpipe_iop_t piece,
const void *const  ivoid,
void *const  ovoid,
const dt_iop_roi_t *const  roi_in,
const dt_iop_roi_t *const  roi_out 
)

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, dt_dev_pixelpipe_iop_t::colors, 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_Lab(), 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_iop_filmic_data_t::output_power, dt_dev_pixelpipe_iop_t::pipe, dt_iop_filmic_data_t::preserve_color, dt_iop_filmic_data_t::table, TRUE, and dt_iop_roi_t::width.

◆ 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()

static void white_point_target_callback ( GtkWidget *  slider,
gpointer  user_data 
)
static