@@ -306,6 +306,8 @@ typedef struct dt_iop_toneequalizer_gui_data_t
306
306
// interactive view are in bounds
307
307
gboolean factors_valid ; // TRUE if radial-basis coeffs are ready
308
308
309
+ gboolean commit_ok ; // to be checked in process for correct smoothing pseudo_solve
310
+ // set while committing
309
311
gboolean distort_signal_actif ;
310
312
} dt_iop_toneequalizer_gui_data_t ;
311
313
@@ -990,6 +992,10 @@ static inline void display_luminance_mask(const float *const restrict in,
990
992
}
991
993
}
992
994
995
+ static inline void _bad_curve (void )
996
+ {
997
+ dt_control_log (_ ("the interpolation is unstable, decrease the curve smoothing" ));
998
+ }
993
999
994
1000
__DT_CLONE_TARGETS__
995
1001
static
@@ -1011,6 +1017,9 @@ void toneeq_process(dt_iop_module_t *self,
1011
1017
const size_t height = roi_in -> height ;
1012
1018
const size_t num_elem = width * height ;
1013
1019
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
+
1014
1023
// Get the hash of the upstream pipe to track changes
1015
1024
const int position = self -> iop_order ;
1016
1025
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,
1039
1048
dt_iop_gui_leave_critical_section (self );
1040
1049
}
1041
1050
1042
- if (piece -> pipe -> type & DT_DEV_PIXELPIPE_FULL )
1051
+ if (is_full )
1043
1052
{
1044
1053
// For DT_DEV_PIXELPIPE_FULL, we cache the luminance mask for performance
1045
1054
// but it's not accessed from GUI
@@ -1057,7 +1066,7 @@ void toneeq_process(dt_iop_module_t *self,
1057
1066
luminance = g -> full_preview_buf ;
1058
1067
cached = TRUE;
1059
1068
}
1060
- else if (piece -> pipe -> type & DT_DEV_PIXELPIPE_PREVIEW )
1069
+ else if (is_preview )
1061
1070
{
1062
1071
// For DT_DEV_PIXELPIPE_PREVIEW, we need to cache it too to
1063
1072
// compute the full image stats upon user request in GUI threads
@@ -1103,7 +1112,7 @@ void toneeq_process(dt_iop_module_t *self,
1103
1112
{
1104
1113
// caching path : store the luminance mask for GUI access
1105
1114
1106
- if (piece -> pipe -> type & DT_DEV_PIXELPIPE_FULL )
1115
+ if (is_full )
1107
1116
{
1108
1117
dt_hash_t saved_hash ;
1109
1118
hash_set_get (& g -> ui_preview_hash , & saved_hash , & self -> gui_lock );
@@ -1119,7 +1128,7 @@ void toneeq_process(dt_iop_module_t *self,
1119
1128
hash_set_get (& hash , & g -> ui_preview_hash , & self -> gui_lock );
1120
1129
}
1121
1130
}
1122
- else if (piece -> pipe -> type & DT_DEV_PIXELPIPE_PREVIEW )
1131
+ else if (is_preview )
1123
1132
{
1124
1133
dt_hash_t saved_hash ;
1125
1134
hash_set_get (& g -> thumb_preview_hash , & saved_hash , & self -> gui_lock );
@@ -1152,19 +1161,15 @@ void toneeq_process(dt_iop_module_t *self,
1152
1161
}
1153
1162
1154
1163
// Display output
1155
- if (self -> dev -> gui_attached && ( piece -> pipe -> type & DT_DEV_PIXELPIPE_FULL ) )
1164
+ if (g && is_full && g -> mask_display )
1156
1165
{
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 ;
1164
1168
}
1165
1169
else
1166
1170
{
1167
1171
apply_toneequalizer (in , luminance , out , roi_in , roi_out , d );
1172
+ if (g && !g -> commit_ok && is_preview ) _bad_curve ();
1168
1173
}
1169
1174
1170
1175
if (!cached ) dt_free_align (luminance );
@@ -1355,6 +1360,7 @@ static void gui_cache_init(dt_iop_module_t *self)
1355
1360
g -> graph_valid = FALSE; // TRUE if the UI graph view is ready
1356
1361
g -> user_param_valid = FALSE; // TRUE if users params set in interactive view are in bounds
1357
1362
g -> factors_valid = TRUE; // TRUE if radial-basis coeffs are ready
1363
+ g -> commit_ok = TRUE;
1358
1364
1359
1365
g -> valid_nodes_x = FALSE; // TRUE if x coordinates of graph nodes have been inited
1360
1366
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,
1517
1523
}
1518
1524
}
1519
1525
1520
-
1521
-
1522
1526
static inline gboolean update_curve_lut (dt_iop_module_t * self )
1523
1527
{
1524
1528
dt_iop_toneequalizer_params_t * p = self -> params ;
1525
1529
dt_iop_toneequalizer_gui_data_t * g = self -> gui_data ;
1526
1530
1527
- if (g == NULL ) return FALSE;
1528
-
1531
+ if (g == NULL ) return TRUE;
1529
1532
gboolean valid = TRUE;
1530
1533
1531
1534
dt_iop_gui_enter_critical_section (self );
@@ -1610,9 +1613,7 @@ void commit_params(dt_iop_module_t *self,
1610
1613
d -> contrast_boost = exp2f (p -> contrast_boost );
1611
1614
d -> exposure_boost = exp2f (p -> exposure_boost );
1612
1615
1613
- /*
1614
- * Perform a radial-based interpolation using a series gaussian functions
1615
- */
1616
+ /* Perform a radial-based interpolation using a series gaussian functions. */
1616
1617
if (self -> dev -> gui_attached && g )
1617
1618
{
1618
1619
dt_iop_gui_enter_critical_section (self );
@@ -1621,9 +1622,8 @@ void commit_params(dt_iop_module_t *self,
1621
1622
g -> sigma = p -> smoothing ;
1622
1623
g -> user_param_valid = FALSE; // force updating channels factors
1623
1624
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;
1627
1627
dt_iop_gui_enter_critical_section (self );
1628
1628
dt_simd_memcpy (g -> factors , d -> factors , PIXEL_CHAN );
1629
1629
dt_iop_gui_leave_critical_section (self );
@@ -1766,19 +1766,14 @@ static void smoothing_callback(GtkWidget *slider, dt_iop_module_t *self)
1766
1766
if (darktable .gui -> reset ) return ;
1767
1767
dt_iop_toneequalizer_params_t * p = self -> params ;
1768
1768
dt_iop_toneequalizer_gui_data_t * g = self -> gui_data ;
1769
-
1769
+ g -> user_param_valid = FALSE;
1770
1770
p -> smoothing = powf (sqrtf (2.0f ), 1.0f + dt_bauhaus_slider_get (slider ));
1771
1771
1772
- float factors [CHANNELS ] DT_ALIGNED_ARRAY ;
1773
- get_channels_factors (factors , p );
1774
-
1775
1772
// Solve the interpolation by least-squares to check the validity of the smoothing param
1773
+ // and possibly warn
1776
1774
if (!update_curve_lut (self ))
1777
- dt_control_log
1778
- (_ ("the interpolation is unstable, decrease the curve smoothing" ));
1779
-
1775
+ _bad_curve ();
1780
1776
// Redraw graph before launching computation
1781
- // Don't do this again: update_curve_lut(self);
1782
1777
gtk_widget_queue_draw (GTK_WIDGET (g -> area ));
1783
1778
dt_dev_add_history_item (darktable .develop , self , TRUE);
1784
1779
@@ -2118,9 +2113,7 @@ int mouse_leave(dt_iop_module_t *self)
2118
2113
2119
2114
static inline gboolean set_new_params_interactive (const float control_exposure ,
2120
2115
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 )
2124
2117
{
2125
2118
// Apply an exposure offset optimized smoothly over all the exposure channels,
2126
2119
// 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,
2129
2122
// Raise the user params accordingly to control correction and
2130
2123
// distance from cursor exposure to blend smoothly the desired
2131
2124
// 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 ;
2132
2128
const float std = gaussian_denom (blending_sigma );
2133
2129
if (g -> user_param_valid )
2134
2130
{
@@ -2143,7 +2139,7 @@ static inline gboolean set_new_params_interactive(const float control_exposure,
2143
2139
if (g -> user_param_valid )
2144
2140
g -> user_param_valid = pseudo_solve (g -> interpolation_matrix , factors , CHANNELS , PIXEL_CHAN , TRUE);
2145
2141
if (!g -> user_param_valid )
2146
- dt_control_log ( _ ( "the interpolation is unstable, decrease the curve smoothing" ) );
2142
+ _bad_curve ( );
2147
2143
2148
2144
// Compute new user params for channels and store them locally
2149
2145
if (g -> user_param_valid )
@@ -2229,8 +2225,7 @@ int scrolled(dt_iop_module_t *self,
2229
2225
2230
2226
// Get the desired correction on exposure channels
2231
2227
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 );
2234
2229
dt_iop_gui_leave_critical_section (self );
2235
2230
2236
2231
gtk_widget_queue_draw (GTK_WIDGET (g -> area ));
@@ -3110,7 +3105,7 @@ static gboolean area_motion_notify(GtkWidget *widget,
3110
3105
if (!self -> enabled ) return FALSE;
3111
3106
3112
3107
dt_iop_toneequalizer_gui_data_t * g = self -> gui_data ;
3113
- dt_iop_toneequalizer_params_t * p = self -> params ;
3108
+ if (! g ) return FALSE ;
3114
3109
3115
3110
if (g -> area_dragging )
3116
3111
{
@@ -3121,8 +3116,7 @@ static gboolean area_motion_notify(GtkWidget *widget,
3121
3116
const float cursor_exposure = g -> area_x / g -> graph_width * 8.0f - 8.0f ;
3122
3117
3123
3118
// 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 );
3126
3120
dt_iop_gui_leave_critical_section (self );
3127
3121
}
3128
3122
0 commit comments