Ansel 0.0
A darktable fork - bloat + design vision
Loading...
Searching...
No Matches
cacorrectrgb.c File Reference
#include "common/extra_optimizations.h"
#include "bauhaus/bauhaus.h"
#include "develop/imageop.h"
#include "develop/imageop_gui.h"
#include "gui/color_picker_proxy.h"
#include "gui/gtk.h"
#include "iop/iop_api.h"
#include "common/gaussian.h"
#include "common/fast_guided_filter.h"
#include <gtk/gtk.h>
#include <stdlib.h>
+ Include dependency graph for cacorrectrgb.c:

Data Structures

struct  dt_iop_cacorrectrgb_params_t
 
struct  dt_iop_cacorrectrgb_gui_data_t
 

Macros

#define DT_CACORRECTRGB_MAX_EV_DIFF   2.0f
 

Typedefs

typedef enum dt_iop_cacorrectrgb_guide_channel_t dt_iop_cacorrectrgb_guide_channel_t
 
typedef enum dt_iop_cacorrectrgb_mode_t dt_iop_cacorrectrgb_mode_t
 
typedef struct dt_iop_cacorrectrgb_params_t dt_iop_cacorrectrgb_params_t
 
typedef struct dt_iop_cacorrectrgb_gui_data_t dt_iop_cacorrectrgb_gui_data_t
 

Enumerations

enum  dt_iop_cacorrectrgb_guide_channel_t {
  DT_CACORRECT_RGB_R = 0 ,
  DT_CACORRECT_RGB_G = 1 ,
  DT_CACORRECT_RGB_B = 2
}
 
enum  dt_iop_cacorrectrgb_mode_t {
  DT_CACORRECT_MODE_STANDARD = 0 ,
  DT_CACORRECT_MODE_DARKEN = 1 ,
  DT_CACORRECT_MODE_BRIGHTEN = 2
}
 

Functions

const char * name ()
 
const char ** description (struct dt_iop_module_t *self)
 
int flags ()
 
int default_group ()
 
int default_colorspace (dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
 
void commit_params (dt_iop_module_t *self, dt_iop_params_t *p1, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
 
static void normalize_manifolds (const float *const restrict blurred_in, float *const restrict blurred_manifold_lower, float *const restrict blurred_manifold_higher, const size_t width, const size_t height, const dt_iop_cacorrectrgb_guide_channel_t guide)
 
static void get_manifolds (const float *const restrict in, const size_t width, const size_t height, const float sigma, const float sigma2, const dt_iop_cacorrectrgb_guide_channel_t guide, float *const restrict manifolds, gboolean refine_manifolds)
 
static void apply_correction (const float *const restrict in, const float *const restrict manifolds, const size_t width, const size_t height, const float sigma, const dt_iop_cacorrectrgb_guide_channel_t guide, const dt_iop_cacorrectrgb_mode_t mode, float *const restrict out)
 
static void reduce_artifacts (const float *const restrict in, const size_t width, const size_t height, const float sigma, const dt_iop_cacorrectrgb_guide_channel_t guide, const float safety, float *const restrict out)
 
static void reduce_chromatic_aberrations (const float *const restrict in, const size_t width, const size_t height, const size_t ch, const float sigma, const float sigma2, const dt_iop_cacorrectrgb_guide_channel_t guide, const dt_iop_cacorrectrgb_mode_t mode, const gboolean refine_manifolds, const float safety, float *const restrict out)
 
void process (struct 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)
 
void gui_update (dt_iop_module_t *self)
 
void reload_defaults (dt_iop_module_t *module)
 
void gui_init (dt_iop_module_t *self)
 

Macro Definition Documentation

◆ DT_CACORRECTRGB_MAX_EV_DIFF

#define DT_CACORRECTRGB_MAX_EV_DIFF   2.0f

Typedef Documentation

◆ dt_iop_cacorrectrgb_gui_data_t

◆ dt_iop_cacorrectrgb_guide_channel_t

Description of the approach

The problem chromatic aberration appear when: (1) channels are misaligned (2) or if some channel is more blurry than another.

example case (1):


_________| first channel


___________| second channel ^^ chromatic aberration

other example case (1):


_________| first channel


|_______ second channel ^^ chromatic aberration

example case (2):


| first channel _________|


/ second channel / ________/ ^^^ chromatic aberration

note that case (1) can already be partially corrected using the lens correction module.

Requirements for the solution

  • handle both cases
  • preserve borders as much as possible
  • be fast to compute

    The solution The main idea is to represent 2 channels as a function of the third one.

a very simple function is: guided = a * guide where a = blur(guided) / blur(guide) But this function is too simple to cope with borders.

We stick with the idea of having guided channel as a factor of the guide channel, but instead of having a locally constant factor a, we use a factor that depends on the value of the guide pixel: guided = a(guide) * guide

Our function a(guide) is pretty simple, it is a weighted average between 2 values (one high and one low), where the weights are dependent on the guide pixel value.

Now, how do we determine these high and low value.

We compute 2 manifolds. manifolds are partial local averages: some pixels are not used in the averages.

for the lower manifold, we average only pixels whose guide value are below a local average of the guide. for the higher manifold, we average only pixels whose guide value are above a local average of the guide.

for example here:


_ _ _ _ _| _ _ _ _ _ _ _ average _________|

^^^^^^^^^ pixels below average (will be used to compute lower manifold)

      ^^^^^^^^^ pixels above average (will be used to compute higher manifold)

As we want to write the guided channel as a ratio of the guide channel, we compute the manifolds on:

  • the guide channel
  • log difference between guide and guided

using the log difference gives much better result than using directly the guided channel in the manifolds computation and computing the ratio after that, because averaging in linear makes lower manifolds harder to estimate accurately. Note that the repartition of pixels into higher and lower manifold computation is done by taking into account ONLY the guide channel.

Once we have our 2 manifolds, with an average log difference for each of them (i.e. an average ratio), we can do a weighted mean to get the result. We weight more one ratio or the other depending to how close the guide pixel is from one manifold or another.

◆ dt_iop_cacorrectrgb_mode_t

◆ dt_iop_cacorrectrgb_params_t

Enumeration Type Documentation

◆ dt_iop_cacorrectrgb_guide_channel_t

Description of the approach

The problem chromatic aberration appear when: (1) channels are misaligned (2) or if some channel is more blurry than another.

example case (1):


_________| first channel


___________| second channel ^^ chromatic aberration

other example case (1):


_________| first channel


|_______ second channel ^^ chromatic aberration

example case (2):


| first channel _________|


/ second channel / ________/ ^^^ chromatic aberration

note that case (1) can already be partially corrected using the lens correction module.

Requirements for the solution

  • handle both cases
  • preserve borders as much as possible
  • be fast to compute

    The solution The main idea is to represent 2 channels as a function of the third one.

a very simple function is: guided = a * guide where a = blur(guided) / blur(guide) But this function is too simple to cope with borders.

We stick with the idea of having guided channel as a factor of the guide channel, but instead of having a locally constant factor a, we use a factor that depends on the value of the guide pixel: guided = a(guide) * guide

Our function a(guide) is pretty simple, it is a weighted average between 2 values (one high and one low), where the weights are dependent on the guide pixel value.

Now, how do we determine these high and low value.

We compute 2 manifolds. manifolds are partial local averages: some pixels are not used in the averages.

for the lower manifold, we average only pixels whose guide value are below a local average of the guide. for the higher manifold, we average only pixels whose guide value are above a local average of the guide.

for example here:


_ _ _ _ _| _ _ _ _ _ _ _ average _________|

^^^^^^^^^ pixels below average (will be used to compute lower manifold)

      ^^^^^^^^^ pixels above average (will be used to compute higher manifold)

As we want to write the guided channel as a ratio of the guide channel, we compute the manifolds on:

  • the guide channel
  • log difference between guide and guided

using the log difference gives much better result than using directly the guided channel in the manifolds computation and computing the ratio after that, because averaging in linear makes lower manifolds harder to estimate accurately. Note that the repartition of pixels into higher and lower manifold computation is done by taking into account ONLY the guide channel.

Once we have our 2 manifolds, with an average log difference for each of them (i.e. an average ratio), we can do a weighted mean to get the result. We weight more one ratio or the other depending to how close the guide pixel is from one manifold or another.

Enumerator
DT_CACORRECT_RGB_R 
DT_CACORRECT_RGB_G 
DT_CACORRECT_RGB_B 

◆ dt_iop_cacorrectrgb_mode_t

Enumerator
DT_CACORRECT_MODE_STANDARD 
DT_CACORRECT_MODE_DARKEN 
DT_CACORRECT_MODE_BRIGHTEN 

Function Documentation

◆ apply_correction()

static void apply_correction ( const float *const restrict  in,
const float *const restrict  manifolds,
const size_t  width,
const size_t  height,
const float  sigma,
const dt_iop_cacorrectrgb_guide_channel_t  guide,
const dt_iop_cacorrectrgb_mode_t  mode,
float *const restrict  out 
)
static

◆ commit_params()

◆ default_colorspace()

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

References IOP_CS_RGB.

◆ default_group()

int default_group ( )

References IOP_GROUP_REPAIR.

◆ description()

const char ** description ( struct dt_iop_module_t self)

◆ flags()

◆ get_manifolds()

static void get_manifolds ( const float *const restrict  in,
const size_t  width,
const size_t  height,
const float  sigma,
const float  sigma2,
const dt_iop_cacorrectrgb_guide_channel_t  guide,
float *const restrict  manifolds,
gboolean  refine_manifolds 
)
static

◆ gui_init()

◆ gui_update()

void gui_update ( dt_iop_module_t self)

◆ name()

const char * name ( )

◆ normalize_manifolds()

static void normalize_manifolds ( const float *const restrict  blurred_in,
float *const restrict  blurred_manifold_lower,
float *const restrict  blurred_manifold_higher,
const size_t  width,
const size_t  height,
const dt_iop_cacorrectrgb_guide_channel_t  guide 
)
static

References for_each_channel, height, and width.

Referenced by get_manifolds().

◆ process()

◆ reduce_artifacts()

static void reduce_artifacts ( const float *const restrict  in,
const size_t  width,
const size_t  height,
const float  sigma,
const dt_iop_cacorrectrgb_guide_channel_t  guide,
const float  safety,
float *const restrict  out 
)
static

◆ reduce_chromatic_aberrations()

static void reduce_chromatic_aberrations ( const float *const restrict  in,
const size_t  width,
const size_t  height,
const size_t  ch,
const float  sigma,
const float  sigma2,
const dt_iop_cacorrectrgb_guide_channel_t  guide,
const dt_iop_cacorrectrgb_mode_t  mode,
const gboolean  refine_manifolds,
const float  safety,
float *const restrict  out 
)
static

◆ reload_defaults()