Skip to content

Commit 8e42e23

Browse files
Tone equalizer UI fixes
- pseudo_solve() problems are tracked while committing the parameters. This means we always have valid runtime reports even if parameters didn't change and we re-open the image in darkroom. - report in interactive mode as there is no pipe running - some refactoring - log report for choleski failing
1 parent d19e145 commit 8e42e23

File tree

2 files changed

+34
-40
lines changed

2 files changed

+34
-40
lines changed

src/common/fast_guided_filter.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,7 @@ static inline void variance_analyse(const float *const restrict guide, // I
199199
ab[2*idx+1] = b;
200200
}
201201

202-
if(input != NULL) dt_free_align(input);
202+
dt_free_align(input);
203203
}
204204

205205

src/iop/toneequal.c

+33-39
Original file line numberDiff line numberDiff line change
@@ -306,6 +306,8 @@ typedef struct dt_iop_toneequalizer_gui_data_t
306306
// interactive view are in bounds
307307
gboolean factors_valid; // TRUE if radial-basis coeffs are ready
308308

309+
gboolean commit_ok; // to be checked in process for correct smoothing pseudo_solve
310+
// set while committing
309311
gboolean distort_signal_actif;
310312
} dt_iop_toneequalizer_gui_data_t;
311313

@@ -990,6 +992,10 @@ static inline void display_luminance_mask(const float *const restrict in,
990992
}
991993
}
992994

995+
static inline void _bad_curve(void)
996+
{
997+
dt_control_log(_("the interpolation is unstable, decrease the curve smoothing"));
998+
}
993999

9941000
__DT_CLONE_TARGETS__
9951001
static
@@ -1011,6 +1017,9 @@ void toneeq_process(dt_iop_module_t *self,
10111017
const size_t height = roi_in->height;
10121018
const size_t num_elem = width * height;
10131019

1020+
const gboolean is_preview = piece->pipe->type & DT_DEV_PIXELPIPE_PREVIEW;
1021+
const gboolean is_full = piece->pipe->type & DT_DEV_PIXELPIPE_FULL;
1022+
10141023
// Get the hash of the upstream pipe to track changes
10151024
const int position = self->iop_order;
10161025
const dt_hash_t hash = dt_dev_pixelpipe_cache_hash(piece->pipe->image.id,
@@ -1039,7 +1048,7 @@ void toneeq_process(dt_iop_module_t *self,
10391048
dt_iop_gui_leave_critical_section(self);
10401049
}
10411050

1042-
if(piece->pipe->type & DT_DEV_PIXELPIPE_FULL)
1051+
if(is_full)
10431052
{
10441053
// For DT_DEV_PIXELPIPE_FULL, we cache the luminance mask for performance
10451054
// but it's not accessed from GUI
@@ -1057,7 +1066,7 @@ void toneeq_process(dt_iop_module_t *self,
10571066
luminance = g->full_preview_buf;
10581067
cached = TRUE;
10591068
}
1060-
else if(piece->pipe->type & DT_DEV_PIXELPIPE_PREVIEW)
1069+
else if(is_preview)
10611070
{
10621071
// For DT_DEV_PIXELPIPE_PREVIEW, we need to cache it too to
10631072
// compute the full image stats upon user request in GUI threads
@@ -1103,7 +1112,7 @@ void toneeq_process(dt_iop_module_t *self,
11031112
{
11041113
// caching path : store the luminance mask for GUI access
11051114

1106-
if(piece->pipe->type & DT_DEV_PIXELPIPE_FULL)
1115+
if(is_full)
11071116
{
11081117
dt_hash_t saved_hash;
11091118
hash_set_get(&g->ui_preview_hash, &saved_hash, &self->gui_lock);
@@ -1119,7 +1128,7 @@ void toneeq_process(dt_iop_module_t *self,
11191128
hash_set_get(&hash, &g->ui_preview_hash, &self->gui_lock);
11201129
}
11211130
}
1122-
else if(piece->pipe->type & DT_DEV_PIXELPIPE_PREVIEW)
1131+
else if(is_preview)
11231132
{
11241133
dt_hash_t saved_hash;
11251134
hash_set_get(&g->thumb_preview_hash, &saved_hash, &self->gui_lock);
@@ -1152,19 +1161,15 @@ void toneeq_process(dt_iop_module_t *self,
11521161
}
11531162

11541163
// Display output
1155-
if(self->dev->gui_attached && (piece->pipe->type & DT_DEV_PIXELPIPE_FULL))
1164+
if(g && is_full && g->mask_display)
11561165
{
1157-
if(g->mask_display)
1158-
{
1159-
display_luminance_mask(in, luminance, out, roi_in, roi_out, 4);
1160-
piece->pipe->mask_display = DT_DEV_PIXELPIPE_DISPLAY_PASSTHRU;
1161-
}
1162-
else
1163-
apply_toneequalizer(in, luminance, out, roi_in, roi_out, d);
1166+
display_luminance_mask(in, luminance, out, roi_in, roi_out, 4);
1167+
piece->pipe->mask_display = DT_DEV_PIXELPIPE_DISPLAY_PASSTHRU;
11641168
}
11651169
else
11661170
{
11671171
apply_toneequalizer(in, luminance, out, roi_in, roi_out, d);
1172+
if(g && !g->commit_ok && is_preview) _bad_curve();
11681173
}
11691174

11701175
if(!cached) dt_free_align(luminance);
@@ -1355,6 +1360,7 @@ static void gui_cache_init(dt_iop_module_t *self)
13551360
g->graph_valid = FALSE; // TRUE if the UI graph view is ready
13561361
g->user_param_valid = FALSE; // TRUE if users params set in interactive view are in bounds
13571362
g->factors_valid = TRUE; // TRUE if radial-basis coeffs are ready
1363+
g->commit_ok = TRUE;
13581364

13591365
g->valid_nodes_x = FALSE; // TRUE if x coordinates of graph nodes have been inited
13601366
g->valid_nodes_y = FALSE; // TRUE if y coordinates of graph nodes have been inited
@@ -1517,15 +1523,12 @@ static inline void compute_lut_correction(dt_iop_toneequalizer_gui_data_t *g,
15171523
}
15181524
}
15191525

1520-
1521-
15221526
static inline gboolean update_curve_lut(dt_iop_module_t *self)
15231527
{
15241528
dt_iop_toneequalizer_params_t *p = self->params;
15251529
dt_iop_toneequalizer_gui_data_t *g = self->gui_data;
15261530

1527-
if(g == NULL) return FALSE;
1528-
1531+
if(g == NULL) return TRUE;
15291532
gboolean valid = TRUE;
15301533

15311534
dt_iop_gui_enter_critical_section(self);
@@ -1610,9 +1613,7 @@ void commit_params(dt_iop_module_t *self,
16101613
d->contrast_boost = exp2f(p->contrast_boost);
16111614
d->exposure_boost = exp2f(p->exposure_boost);
16121615

1613-
/*
1614-
* Perform a radial-based interpolation using a series gaussian functions
1615-
*/
1616+
/* Perform a radial-based interpolation using a series gaussian functions. */
16161617
if(self->dev->gui_attached && g)
16171618
{
16181619
dt_iop_gui_enter_critical_section(self);
@@ -1621,9 +1622,8 @@ void commit_params(dt_iop_module_t *self,
16211622
g->sigma = p->smoothing;
16221623
g->user_param_valid = FALSE; // force updating channels factors
16231624
dt_iop_gui_leave_critical_section(self);
1624-
1625-
update_curve_lut(self);
1626-
1625+
const gboolean curve_ok = update_curve_lut(self);
1626+
g->commit_ok = piece->enabled && (piece->pipe->type & DT_DEV_PIXELPIPE_PREVIEW) ? curve_ok : TRUE;
16271627
dt_iop_gui_enter_critical_section(self);
16281628
dt_simd_memcpy(g->factors, d->factors, PIXEL_CHAN);
16291629
dt_iop_gui_leave_critical_section(self);
@@ -1766,19 +1766,14 @@ static void smoothing_callback(GtkWidget *slider, dt_iop_module_t *self)
17661766
if(darktable.gui->reset) return;
17671767
dt_iop_toneequalizer_params_t *p = self->params;
17681768
dt_iop_toneequalizer_gui_data_t *g = self->gui_data;
1769-
1769+
g->user_param_valid = FALSE;
17701770
p->smoothing= powf(sqrtf(2.0f), 1.0f + dt_bauhaus_slider_get(slider));
17711771

1772-
float factors[CHANNELS] DT_ALIGNED_ARRAY;
1773-
get_channels_factors(factors, p);
1774-
17751772
// Solve the interpolation by least-squares to check the validity of the smoothing param
1773+
// and possibly warn
17761774
if(!update_curve_lut(self))
1777-
dt_control_log
1778-
(_("the interpolation is unstable, decrease the curve smoothing"));
1779-
1775+
_bad_curve();
17801776
// Redraw graph before launching computation
1781-
// Don't do this again: update_curve_lut(self);
17821777
gtk_widget_queue_draw(GTK_WIDGET(g->area));
17831778
dt_dev_add_history_item(darktable.develop, self, TRUE);
17841779

@@ -2118,9 +2113,7 @@ int mouse_leave(dt_iop_module_t *self)
21182113

21192114
static inline gboolean set_new_params_interactive(const float control_exposure,
21202115
const float exposure_offset,
2121-
const float blending_sigma,
2122-
dt_iop_toneequalizer_gui_data_t *g,
2123-
dt_iop_toneequalizer_params_t *p)
2116+
dt_iop_module_t *self)
21242117
{
21252118
// Apply an exposure offset optimized smoothly over all the exposure channels,
21262119
// taking user instruction to apply exposure_offset EV at control_exposure EV,
@@ -2129,6 +2122,9 @@ static inline gboolean set_new_params_interactive(const float control_exposure,
21292122
// Raise the user params accordingly to control correction and
21302123
// distance from cursor exposure to blend smoothly the desired
21312124
// correction
2125+
dt_iop_toneequalizer_gui_data_t *g = self->gui_data;
2126+
dt_iop_toneequalizer_params_t *p = self->params;
2127+
const float blending_sigma = g->sigma * g->sigma / 2.0f;
21322128
const float std = gaussian_denom(blending_sigma);
21332129
if(g->user_param_valid)
21342130
{
@@ -2143,7 +2139,7 @@ static inline gboolean set_new_params_interactive(const float control_exposure,
21432139
if(g->user_param_valid)
21442140
g->user_param_valid = pseudo_solve(g->interpolation_matrix, factors, CHANNELS, PIXEL_CHAN, TRUE);
21452141
if(!g->user_param_valid)
2146-
dt_control_log(_("the interpolation is unstable, decrease the curve smoothing"));
2142+
_bad_curve();
21472143

21482144
// Compute new user params for channels and store them locally
21492145
if(g->user_param_valid)
@@ -2229,8 +2225,7 @@ int scrolled(dt_iop_module_t *self,
22292225

22302226
// Get the desired correction on exposure channels
22312227
dt_iop_gui_enter_critical_section(self);
2232-
const gboolean commit = set_new_params_interactive(g->cursor_exposure, offset,
2233-
g->sigma * g->sigma / 2.0f, g, p);
2228+
const gboolean commit = set_new_params_interactive(g->cursor_exposure, offset, self);
22342229
dt_iop_gui_leave_critical_section(self);
22352230

22362231
gtk_widget_queue_draw(GTK_WIDGET(g->area));
@@ -3110,7 +3105,7 @@ static gboolean area_motion_notify(GtkWidget *widget,
31103105
if(!self->enabled) return FALSE;
31113106

31123107
dt_iop_toneequalizer_gui_data_t *g = self->gui_data;
3113-
dt_iop_toneequalizer_params_t *p = self->params;
3108+
if(!g) return FALSE;
31143109

31153110
if(g->area_dragging)
31163111
{
@@ -3121,8 +3116,7 @@ static gboolean area_motion_notify(GtkWidget *widget,
31213116
const float cursor_exposure = g->area_x / g->graph_width * 8.0f - 8.0f;
31223117

31233118
// Get the desired correction on exposure channels
3124-
g->area_dragging = set_new_params_interactive(cursor_exposure, offset,
3125-
g->sigma * g->sigma / 2.0f, g, p);
3119+
g->area_dragging = set_new_params_interactive(cursor_exposure, offset, self);
31263120
dt_iop_gui_leave_critical_section(self);
31273121
}
31283122

0 commit comments

Comments
 (0)