Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
d6f5d83
agx: Flipped toe and shoulder power + start + target black/white
kofa73 Oct 20, 2025
582d61c
agx: Added "read exposure", setting black/white relative exposure fro…
kofa73 Oct 21, 2025
9471730
agx: Fixed toe/shoulder power warning redraw; fixed 'read exposure'
kofa73 Oct 22, 2025
a6241ce
agx: removed workaround to redraw of toe/shoulder warning, now proper…
kofa73 Oct 23, 2025
058c04e
agx: hue/purity sliders default to 0; removed useless comments and le…
kofa73 Oct 23, 2025
47913ca
agx: turn 'read exposure' into a button, so it can have a shortcut; f…
kofa73 Oct 23, 2025
2acbeb3
agx: added tooltips for pickers
kofa73 Oct 23, 2025
5998b94
agx: separated auto-tune from label
kofa73 Oct 23, 2025
dfd684a
agx: Separate pickers for pivot x and x+y
kofa73 Oct 29, 2025
944342f
agx: Set 'feedback=0' for agx primaries hue and purity sliders for be…
kofa73 Nov 1, 2025
dbb51f4
agx: Removed plugins/darkroom/agx/reverse_hue_for_unrotation; reverse…
kofa73 Nov 1, 2025
7811e08
agx: Added exposure-based relative black/white to reload_defaults
kofa73 Nov 1, 2025
957a6fe
agx: Added _find_preferred_enabled_instance to develop.c (to be moved…
kofa73 Nov 1, 2025
47d0acb
agx: Switched pivot from shift to relative EV
kofa73 Nov 1, 2025
510eeaf
agx: Added dt_iop_get_module_enabled_preferring_unmasked_first_instan…
kofa73 Nov 2, 2025
09bb010
agx: Don't adjust exposure limits for HDR input in reload_defaults
kofa73 Nov 2, 2025
c0f70ae
agx: No 'headless fallback' mode for _exposure_proxy_get_effective_ex…
kofa73 Nov 2, 2025
a18b047
agx: Try to keep pivot output when picking
kofa73 Nov 2, 2025
241645a
agx: Move painting the sliders into the functions _setup_purity_slide…
kofa73 Nov 3, 2025
300be09
agx: Use 'self' instead of 'real_self' where possible.
kofa73 Nov 3, 2025
f2a2b1a
agx: curve_pivot_x_relative_ev -> curve_pivot_x (WIP)
kofa73 Nov 7, 2025
302d8be
agx: curve_pivot_x_relative_ev -> curve_pivot_x struggling
kofa73 Nov 8, 2025
94eae1a
agx: exposure pickers work, pivot pickers stopped working
kofa73 Nov 8, 2025
2702355
agx: all pickers work
kofa73 Nov 8, 2025
9d0621d
agx: all pickers work
kofa73 Nov 9, 2025
5de52a2
agx: range_white_relative_ev soft limit 10 EV
kofa73 Nov 9, 2025
d93c41a
agx: update pivot_x default according to exposure params, so double-c…
kofa73 Nov 9, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 37 additions & 0 deletions src/develop/develop.c
Original file line number Diff line number Diff line change
Expand Up @@ -2951,6 +2951,43 @@ float dt_dev_exposure_get_exposure(dt_develop_t *dev)
return instance && instance->get_exposure && instance->module->enabled ? instance->get_exposure(instance->module) : 0.0f;
}

float dt_dev_exposure_get_effective_exposure(dt_develop_t *dev)
{
if (dt_view_get_current() != DT_VIEW_DARKROOM)
{
return 0.0f;
}

// The proxy function pointers are only set if an exposure module has been initialized.
if (!dev->proxy.exposure.get_effective_exposure)
{
return 0.0f;
}

const dt_iop_module_so_t *exposure_so = NULL;

for(const GList *modules = darktable.iop; modules; modules = g_list_next(modules))
{
const dt_iop_module_so_t *module_so = modules->data;
if(dt_iop_module_is(module_so, "exposure"))
{
exposure_so = module_so;
break;
}
}

if (exposure_so)
{
dt_iop_module_t *preferred_exposure_instance = dt_iop_get_module_enabled_preferring_unmasked_first_instance(exposure_so);
if (preferred_exposure_instance)
{
return dev->proxy.exposure.get_effective_exposure(preferred_exposure_instance);
}
}

return 0.0f;
}

float dt_dev_exposure_get_black(dt_develop_t *dev)
{
const dt_dev_proxy_exposure_t *instance = _dev_exposure_proxy_available(dev);
Expand Down
3 changes: 3 additions & 0 deletions src/develop/develop.h
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ typedef struct dt_dev_proxy_exposure_t
{
struct dt_iop_module_t *module;
float (*get_exposure)(struct dt_iop_module_t *exp);
float (*get_effective_exposure)(struct dt_iop_module_t *exp);
float (*get_black)(struct dt_iop_module_t *exp);
void (*handle_event)(gpointer, int, gdouble, const gboolean);
} dt_dev_proxy_exposure_t;
Expand Down Expand Up @@ -468,6 +469,8 @@ void dt_dev_configure(dt_dev_viewport_t *port);

/** get exposure level */
float dt_dev_exposure_get_exposure(dt_develop_t *dev);
/** get final effective exposure level including compensations */
float dt_dev_exposure_get_effective_exposure(dt_develop_t *dev);
/** get exposure black level */
float dt_dev_exposure_get_black(dt_develop_t *dev);

Expand Down
26 changes: 23 additions & 3 deletions src/develop/imageop.c
Original file line number Diff line number Diff line change
Expand Up @@ -3636,9 +3636,16 @@ dt_iop_module_t *dt_iop_get_module_by_op_priority(GList *modules,
return mod_ret;
}

typedef enum instance_filter_mode_t
{
FILTER_NEUTRAL,
FILTER_PREFER,
FILTER_REQUIRE,
} instance_filter_mode_t;

dt_iop_module_t *_find_preferred_instance(const dt_iop_module_so_t *module,
const gboolean prefer_expanded,
const gboolean prefer_enabled,
const instance_filter_mode_t enabled_mode,
const gboolean prefer_unmasked,
const gboolean prefer_first)
{
Expand All @@ -3653,6 +3660,10 @@ dt_iop_module_t *_find_preferred_instance(const dt_iop_module_so_t *module,

if(mod->so == module && mod->iop_order != INT_MAX)
{
if (enabled_mode == FILTER_REQUIRE && !mod->enabled) continue;

const gboolean prefer_enabled = enabled_mode == FILTER_PREFER;

const gboolean no_mask = mod->blend_params->mask_mode == DEVELOP_MASK_DISABLED
|| mod->blend_params->mask_mode == DEVELOP_MASK_ENABLED;
const int score = (mod->expanded && prefer_expanded ? 8 : 0)
Expand Down Expand Up @@ -3704,11 +3715,20 @@ dt_iop_module_t *dt_iop_get_module_preferred_instance(const dt_iop_module_so_t *
else
return _find_preferred_instance(module,
dt_conf_get_bool("accel/prefer_expanded"),
dt_conf_get_bool("accel/prefer_enabled"),
dt_conf_get_bool("accel/prefer_enabled") ? FILTER_PREFER : FILTER_NEUTRAL,
dt_conf_get_bool("accel/prefer_unmasked"),
dt_conf_is_equal("accel/select_order", "first instance"));
}

dt_iop_module_t *dt_iop_get_module_enabled_preferring_unmasked_first_instance(const dt_iop_module_so_t *module)
{
return _find_preferred_instance(module,
FALSE,
FILTER_REQUIRE,
TRUE,
TRUE);
}

/** adds keyboard accels to the first module in the pipe to handle
* where there are multiple instances */
void dt_iop_connect_accels_multi(dt_iop_module_so_t *module)
Expand All @@ -3723,7 +3743,7 @@ void dt_iop_connect_accels_multi(dt_iop_module_so_t *module)

if(!strcmp(module->op, "exposure"))
darktable.develop->proxy.exposure.module =
_find_preferred_instance(module, FALSE, TRUE, TRUE, TRUE);
_find_preferred_instance(module, FALSE, FILTER_PREFER, TRUE, TRUE);
}

void dt_iop_connect_accels_all(void)
Expand Down
3 changes: 3 additions & 0 deletions src/develop/imageop.h
Original file line number Diff line number Diff line change
Expand Up @@ -457,6 +457,9 @@ int dt_iop_count_instances(dt_iop_module_so_t *module);
/** return preferred module instance for shortcuts **/
dt_iop_module_t *dt_iop_get_module_preferred_instance(const dt_iop_module_so_t *module);

/** return an enabled instance, if any, preferring unmasked instances earlier in the pipe **/
dt_iop_module_t *dt_iop_get_module_enabled_preferring_unmasked_first_instance(const dt_iop_module_so_t *module);

/** returns true if module is the first instance of this operation in the pipe */
gboolean dt_iop_is_first_instance(GList *modules, const dt_iop_module_t *module);

Expand Down
Loading
Loading