![]() |
Ansel 0.0
A darktable fork - bloat + design vision
|
#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>
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) |
#define DT_CACORRECTRGB_MAX_EV_DIFF 2.0f |
typedef struct dt_iop_cacorrectrgb_gui_data_t dt_iop_cacorrectrgb_gui_data_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
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:
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.
typedef enum dt_iop_cacorrectrgb_mode_t dt_iop_cacorrectrgb_mode_t |
typedef struct dt_iop_cacorrectrgb_params_t dt_iop_cacorrectrgb_params_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
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:
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 |
|
static |
References DT_CACORRECT_MODE_BRIGHTEN, DT_CACORRECT_MODE_DARKEN, DT_CACORRECT_MODE_STANDARD, height, weight(), and width.
Referenced by reduce_chromatic_aberrations().
void commit_params | ( | dt_iop_module_t * | self, |
dt_iop_params_t * | p1, | ||
dt_dev_pixelpipe_t * | pipe, | ||
dt_dev_pixelpipe_iop_t * | piece | ||
) |
References dt_dev_pixelpipe_iop_t::data, and dt_iop_module_t::params_size.
int default_colorspace | ( | dt_iop_module_t * | self, |
dt_dev_pixelpipe_t * | pipe, | ||
dt_dev_pixelpipe_iop_t * | piece | ||
) |
References IOP_CS_RGB.
int default_group | ( | ) |
References IOP_GROUP_REPAIR.
const char ** description | ( | struct dt_iop_module_t * | self | ) |
References dt_iop_set_description().
int flags | ( | ) |
References IOP_FLAGS_INCLUDE_IN_STYLES, and IOP_FLAGS_SUPPORTS_BLENDING.
|
static |
References dt_alloc_align_float(), DT_CACORRECTRGB_MAX_EV_DIFF, dt_free_align, dt_gaussian_blur_4c(), dt_gaussian_free(), dt_gaussian_init(), error(), for_four_channels, height, normalize_manifolds(), and width.
Referenced by reduce_chromatic_aberrations().
void gui_init | ( | dt_iop_module_t * | self | ) |
void gui_update | ( | dt_iop_module_t * | self | ) |
References dt_iop_module_t::gui_data, and dt_iop_module_t::params.
const char * name | ( | ) |
|
static |
References for_each_channel, height, and width.
Referenced by get_manifolds().
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 | ||
) |
References dt_dev_pixelpipe_iop_t::colors, dt_dev_pixelpipe_iop_t::data, dt_iop_have_required_input_format(), dt_iop_cacorrectrgb_params_t::guide_channel, height, dt_iop_roi_t::height, dt_dev_pixelpipe_iop_t::iscale, dt_iop_cacorrectrgb_params_t::mode, dt_iop_cacorrectrgb_params_t::radius, reduce_chromatic_aberrations(), dt_iop_cacorrectrgb_params_t::refine_manifolds, dt_iop_roi_t::scale, dt_iop_cacorrectrgb_params_t::strength, width, and dt_iop_roi_t::width.
|
static |
References DT_ALIGNED_PIXEL, dt_alloc_align_float(), dt_free_align, dt_gaussian_blur_4c(), dt_gaussian_free(), dt_gaussian_init(), height, and width.
Referenced by reduce_chromatic_aberrations().
|
static |
References apply_correction(), dt_alloc_align_float(), dt_free_align, error(), get_manifolds(), height, interpolate_bilinear(), reduce_artifacts(), and width.
Referenced by process().
void reload_defaults | ( | dt_iop_module_t * | module | ) |
References dt_iop_module_t::default_params, dt_bauhaus_combobox_set_default(), dt_bauhaus_slider_set_default(), dt_bauhaus_slider_set_soft_range(), DT_CACORRECT_MODE_STANDARD, DT_CACORRECT_RGB_G, FALSE, dt_iop_module_t::gui_data, dt_iop_cacorrectrgb_params_t::guide_channel, dt_iop_cacorrectrgb_params_t::mode, dt_iop_cacorrectrgb_params_t::radius, dt_iop_cacorrectrgb_params_t::refine_manifolds, and dt_iop_cacorrectrgb_params_t::strength.