Krolyxon
Commit 95bc9b4

Branches

Refs →

nsxiv95bc9b4

add brightness and contrast (#396)

* Imlib2 supports modifying gamma, brightness and contrast directly
  while sxiv only supports gamma. Makes sense to extend it to brightness
  and contrast as well.

* Since color corrections need to be aware of each other, they have been
  refactored into one centralized function.

* This also makes the code more hackable as it makes it easier to add
  more color correction functions without them interfering with each
  other.
Author
Berke Kocaoğlu
Date
2022-12-22 11:21 +0000
Committer
NRK · 2022-12-22 11:21 +0000
Parent
9cb9a54
Commit
95bc9b463b87236d30d86626e1052e6979d6510f

+92 −35

7 files changed

  1. M commands.c +20 −7
  2. M commands.h +4 −0
  3. M config.def.h +11 −4
  4. M etc/nsxiv.1 +20 −0
  5. M image.c +29 −23
  6. M main.c +4 −0
  7. M nsxiv.h +4 −1
M commands.c View
@@ -222,15 +222,28 @@ bool cg_navigate_marked(arg_t n)
222222 return navigate_to(new);
223223 }
224224
225−bool cg_change_gamma(arg_t d)
225+static bool change_color_modifier(arg_t d, int *target)
226226 {
227− if (img_change_gamma(&img, d * (prefix > 0 ? prefix : 1))) {
228− if (mode == MODE_THUMB)
229− tns.dirty = true;
230− return true;
231− } else {
227+ if (!img_change_color_modifier(&img, d * (prefix > 0 ? prefix : 1), target))
232228 return false;
233− }
229+ if (mode == MODE_THUMB)
230+ tns.dirty = true;
231+ return true;
232+}
233+
234+bool cg_change_gamma(arg_t d)
235+{
236+ return change_color_modifier(d, &img.gamma);
237+}
238+
239+bool cg_change_brightness(arg_t d)
240+{
241+ return change_color_modifier(d, &img.brightness);
242+}
243+
244+bool cg_change_contrast(arg_t d)
245+{
246+ return change_color_modifier(d, &img.contrast);
234247 }
235248
236249 bool ci_navigate(arg_t n)
M commands.h View
@@ -4,6 +4,8 @@
44
55 /* global */
66 bool cg_change_gamma(arg_t);
7+bool cg_change_brightness(arg_t);
8+bool cg_change_contrast(arg_t);
79 bool cg_first(arg_t);
810 bool cg_mark_range(arg_t);
911 bool cg_n_or_last(arg_t);
@@ -47,6 +49,8 @@ bool ct_select(arg_t);
4749 #ifdef INCLUDE_MAPPINGS_CONFIG
4850 /* global */
4951 #define g_change_gamma { cg_change_gamma, MODE_ALL }
52+#define g_change_brightness { cg_change_brightness, MODE_ALL }
53+#define g_change_contrast { cg_change_contrast, MODE_ALL }
5054 #define g_first { cg_first, MODE_ALL }
5155 #define g_mark_range { cg_mark_range, MODE_ALL }
5256 #define g_n_or_last { cg_n_or_last, MODE_ALL }
M config.def.h View
@@ -33,11 +33,14 @@ static const float zoom_levels[] = {
3333 /* default slideshow delay (in sec, overwritten via -S option): */
3434 static const int SLIDESHOW_DELAY = 5;
3535
36−/* gamma correction: the user-visible ranges [-GAMMA_RANGE, 0] and
37− * (0, GAMMA_RANGE] are mapped to the ranges [0, 1], and (1, GAMMA_MAX].
36+/* color correction: the user-visible ranges [-CC_STEPS, 0] and
37+ * (0, CC_STEPS] are mapped to the ranges [0, 1], and (1, *_MAX].
38+ * Higher step count will have higher granulairy.
3839 */
39−static const double GAMMA_MAX = 10.0;
40−static const int GAMMA_RANGE = 32;
40+static const int CC_STEPS = 32;
41+static const double GAMMA_MAX = 10.0;
42+static const double BRIGHTNESS_MAX = 2.0;
43+static const double CONTRAST_MAX = 4.0;
4144
4245 /* command i_scroll pans image 1/PAN_FRACTION of screen width/height */
4346 static const int PAN_FRACTION = 5;
@@ -118,6 +121,10 @@ static const keymap_t keys[] = {
118121 { 0, XK_braceleft, g_change_gamma, -1 },
119122 { 0, XK_braceright, g_change_gamma, +1 },
120123 { ControlMask, XK_g, g_change_gamma, 0 },
124+ { ControlMask, XK_bracketright, g_change_brightness, +1 },
125+ { ControlMask, XK_bracketleft, g_change_brightness, -1 },
126+ { 0, XK_parenleft, g_change_contrast, -1 },
127+ { 0, XK_parenright, g_change_contrast, +1 },
121128
122129 { 0, XK_h, t_move_sel, DIR_LEFT },
123130 { 0, XK_Left, t_move_sel, DIR_LEFT },
M etc/nsxiv.1 View
@@ -209,6 +209,26 @@ steps.
209209 .TP
210210 .B Ctrl-g
211211 Reset gamma correction.
212+.TP
213+.B [
214+Decrease brightness correction by
215+.I count
216+steps.
217+.TP
218+.B ]
219+Increase brightness correction by
220+.I count
221+steps.
222+.TP
223+.B (
224+Decrease contrast by
225+.I count
226+steps.
227+.TP
228+.B )
229+Increase contrast by
230+.I count
231+steps.
212232 .SS Thumbnail mode
213233 The following keyboard commands are only available in thumbnail mode:
214234 .TP
M image.c View
@@ -90,7 +90,9 @@ void img_init(img_t *img, win_t *win)
9090
9191 img->cmod = imlib_create_color_modifier();
9292 imlib_context_set_color_modifier(img->cmod);
93− img_change_gamma(img, options->gamma);
93+ img->brightness = 0;
94+ img->contrast = 0;
95+ img_change_color_modifier(img, options->gamma, &img->gamma);
9496
9597 img->ss.on = options->slideshow > 0;
9698 img->ss.delay = options->slideshow > 0 ? options->slideshow : SLIDESHOW_DELAY * 10u;
@@ -840,32 +842,36 @@ void img_toggle_antialias(img_t *img)
840842 img->dirty = true;
841843 }
842844
843−bool img_change_gamma(img_t *img, int d)
845+static double steps_to_range(int d, double max, double offset)
844846 {
845− /* d < 0: decrease gamma
846− * d = 0: reset gamma
847− * d > 0: increase gamma
848− */
849− int gamma;
850− double range;
847+ return offset + d * ((d <= 0 ? 1.0 : (max - 1.0)) / CC_STEPS);
848+}
851849
852− if (d == 0)
853− gamma = 0;
854− else
855− gamma = MIN(MAX(img->gamma + d, -GAMMA_RANGE), GAMMA_RANGE);
850+void img_update_color_modifiers(img_t *img)
851+{
852+ assert(imlib_context_get_color_modifier() == img->cmod);
853+ imlib_reset_color_modifier();
856854
857− if (img->gamma != gamma) {
858− imlib_reset_color_modifier();
859− if (gamma) {
860− range = gamma <= 0 ? 1.0 : GAMMA_MAX - 1.0;
861− imlib_modify_color_modifier_gamma(1.0 + gamma * (range / GAMMA_RANGE));
862− }
863− img->gamma = gamma;
864− img->dirty = true;
865− return true;
866− } else {
855+ if (img->gamma != 0)
856+ imlib_modify_color_modifier_gamma(steps_to_range(img->gamma, GAMMA_MAX, 1.0));
857+ if (img->brightness != 0)
858+ imlib_modify_color_modifier_brightness(steps_to_range(img->brightness, BRIGHTNESS_MAX, 0.0));
859+ if (img->contrast != 0)
860+ imlib_modify_color_modifier_contrast(steps_to_range(img->contrast, CONTRAST_MAX, 1.0));
861+
862+ img->dirty = true;
863+}
864+
865+bool img_change_color_modifier(img_t *img, int d, int *target)
866+{
867+ int value = d == 0 ? 0 : MIN(MAX(*target + d, -CC_STEPS), CC_STEPS);
868+
869+ if (*target == value)
867870 return false;
868− }
871+
872+ *target = value;
873+ img_update_color_modifiers(img);
874+ return true;
869875 }
870876
871877 static bool img_frame_goto(img_t *img, int n)
M main.c View
@@ -444,6 +444,10 @@ static void update_info(void)
444444 }
445445 if (img.gamma)
446446 bar_put(r, "G%+d" BAR_SEP, img.gamma);
447+ if (img.brightness)
448+ bar_put(r, "B%+d" BAR_SEP, img.brightness);
449+ if (img.contrast)
450+ bar_put(r, "C%+d" BAR_SEP, img.contrast);
447451 bar_put(r, "%3d%%" BAR_SEP, (int) (img.zoom * 100.0));
448452 if (img.multi.cnt > 0) {
449453 for (fn = 0, i = img.multi.cnt; i > 0; fn++, i /= 10);
M nsxiv.h View
@@ -181,6 +181,8 @@ struct img {
181181
182182 Imlib_Color_Modifier cmod;
183183 int gamma;
184+ int brightness;
185+ int contrast;
184186
185187 scalemode_t scalemode;
186188 float zoom;
@@ -212,7 +214,8 @@ bool img_pan_edge(img_t*, direction_t);
212214 void img_rotate(img_t*, degree_t);
213215 void img_flip(img_t*, flipdir_t);
214216 void img_toggle_antialias(img_t*);
215−bool img_change_gamma(img_t*, int);
217+void img_update_color_modifiers(img_t*);
218+bool img_change_color_modifier(img_t*, int, int*);
216219 bool img_frame_navigate(img_t*, int);
217220 bool img_frame_animate(img_t*);
218221 Imlib_Image img_open(const fileinfo_t*);