diff --git a/commands.c b/commands.c
index ff95f36..20557e5 100644
--- a/commands.c
+++ b/commands.c
@@ -474,6 +474,22 @@ bool i_toggle_antialias(arg_t a)
 	}
 }
 
+/* a < 0:  decrease gamma
+ * a == 0: reset gamma
+ * a > 0:  increase gamma
+ */
+bool i_change_gamma(arg_t a)
+{
+	if (mode == MODE_IMAGE) {
+		long val = (long) a;
+		int delta = val > 0 ? 1 : (val < 0 ? -1 : -img.gamma);
+		img_set_gamma(&img, img.gamma + delta);
+		return true;
+	} else {
+		return false;
+	}
+}
+
 bool it_toggle_alpha(arg_t a)
 {
 	img.alpha = tns.alpha = !img.alpha;
diff --git a/commands.h b/commands.h
index 118c89a..16aee07 100644
--- a/commands.h
+++ b/commands.h
@@ -67,6 +67,7 @@ bool i_fit_to_img(arg_t);
 bool i_rotate(arg_t);
 bool i_flip(arg_t);
 bool i_toggle_antialias(arg_t);
+bool i_change_gamma(arg_t);
 bool it_toggle_alpha(arg_t);
 bool it_open_with(arg_t);
 bool it_shell_cmd(arg_t);
diff --git a/config.def.h b/config.def.h
index f5d048a..b877aa1 100644
--- a/config.def.h
+++ b/config.def.h
@@ -46,6 +46,12 @@ enum {
 	GIF_LOOP     = 0    /* endless loop [0/1] */
 };
 
+/* gamma correction: the user-visible ranges [-GAMMA_RANGE, 0] and
+ * (0, GAMMA_RANGE] are mapped to the ranges [0, 1], and (1, GAMMA_MAX].
+ * */
+static const double GAMMA_MAX = 10.0;
+static const int GAMMA_RANGE = 32;
+
 #endif
 #ifdef _THUMBS_CONFIG
 
@@ -141,6 +147,11 @@ static const keymap_t keys[] = {
 	{ false,  XK_a,             i_toggle_antialias,   (arg_t) None },
 	{ false,  XK_A,             it_toggle_alpha,      (arg_t) None },
 
+	/* decrease/increase/reset gamma */
+	{ false,  XK_braceleft,     i_change_gamma,       (arg_t) -1 },
+	{ false,  XK_braceright,    i_change_gamma,       (arg_t) +1 },
+	{ true,   XK_G,             i_change_gamma,       (arg_t) 0 },
+
 	/* open current image with given program: */
 	{ true,   XK_g,             it_open_with,         (arg_t) "gimp" },
 
diff --git a/image.c b/image.c
index ec248e1..b1c7851 100644
--- a/image.c
+++ b/image.c
@@ -67,6 +67,9 @@ void img_init(img_t *img, win_t *win)
 	img->alpha = !RENDER_WHITE_ALPHA;
 	img->multi.cap = img->multi.cnt = 0;
 	img->multi.animate = false;
+
+	img->cmod = imlib_create_color_modifier();
+	img_set_gamma(img, options->gamma);
 }
 
 void exif_auto_orientate(const fileinfo_t *file)
@@ -303,6 +306,8 @@ bool img_load(img_t *img, const fileinfo_t *file)
 		img_load_gif(img, file);
 #endif
 
+	img_set_gamma(img, img->gamma);
+
 	img->w = imlib_image_get_width();
 	img->h = imlib_image_get_height();
 	img->scalemode = options->scalemode;
@@ -335,6 +340,9 @@ void img_close(img_t *img, bool decache)
 			imlib_free_image();
 		img->im = NULL;
 	}
+
+	if (img->cmod)
+		imlib_context_set_color_modifier(NULL);
 }
 
 void img_check_pan(img_t *img, bool moved)
@@ -706,6 +714,28 @@ void img_toggle_antialias(img_t *img)
 	img->dirty = true;
 }
 
+void img_set_gamma(img_t *img, int gamma)
+{
+	if (img == NULL)
+		return;
+
+	img->gamma = MIN(MAX(gamma, -GAMMA_RANGE), GAMMA_RANGE);
+
+	if (img->im && img->cmod) {
+		if (img->gamma == 0) {
+			imlib_context_set_color_modifier(NULL);
+		} else {
+			double range = img->gamma <= 0 ? 1.0 : GAMMA_MAX - 1.0;
+			imlib_context_set_color_modifier(img->cmod);
+			imlib_reset_color_modifier();
+			imlib_modify_color_modifier_gamma(
+				1.0 + (double) img->gamma
+				* (range / (double) GAMMA_RANGE));
+		}
+		img->dirty = true;
+	}
+}
+
 bool img_frame_goto(img_t *img, int n)
 {
 	if (img == NULL || img->im == NULL)
diff --git a/image.h b/image.h
index 9a4efe6..7ed104e 100644
--- a/image.h
+++ b/image.h
@@ -55,6 +55,9 @@ typedef struct {
 	bool aa;
 	bool alpha;
 
+	Imlib_Color_Modifier cmod;
+	int gamma;
+
 	multi_img_t multi;
 } img_t;
 
@@ -81,6 +84,8 @@ void img_flip(img_t*, flipdir_t);
 
 void img_toggle_antialias(img_t*);
 
+void img_set_gamma(img_t*, int);
+
 bool img_frame_navigate(img_t*, int);
 bool img_frame_animate(img_t*, bool);
 
diff --git a/main.c b/main.c
index eac3574..376898d 100644
--- a/main.c
+++ b/main.c
@@ -352,6 +352,8 @@ void update_info(void)
 			n += snprintf(rt + n, rlen - n, "%0*d/%d | ",
 			              fn, img.multi.sel + 1, img.multi.cnt);
 		}
+		if (img.gamma != 0)
+			n += snprintf(rt + n, rlen - n, "g%d | ", img.gamma);
 		n += snprintf(rt + n, rlen - n, "%0*d/%d", fw, sel + 1, filecnt);
 		ow_info = info.script == NULL;
 	}
diff --git a/options.c b/options.c
index e47ad37..574f871 100644
--- a/options.c
+++ b/options.c
@@ -33,7 +33,7 @@ const options_t *options = (const options_t*) &_options;
 
 void print_usage(void)
 {
-	printf("usage: sxiv [-bcdFfhioqrstvZ] [-g GEOMETRY] [-n NUM] "
+	printf("usage: sxiv [-bcdFfhioqrstvZ] [-g GEOMETRY] [-G GAMMA] [-n NUM] "
 	       "[-N name] [-z ZOOM] FILES...\n");
 }
 
@@ -44,7 +44,7 @@ void print_version(void)
 
 void parse_options(int argc, char **argv)
 {
-	int opt, t;
+	int opt, t, gamma;
 
 	_options.from_stdin = false;
 	_options.to_stdout = false;
@@ -53,6 +53,7 @@ void parse_options(int argc, char **argv)
 
 	_options.scalemode = SCALE_MODE;
 	_options.zoom = 1.0;
+	_options.gamma = 0;
 
 	_options.fixed_win = false;
 	_options.fullscreen = false;
@@ -64,7 +65,7 @@ void parse_options(int argc, char **argv)
 	_options.thumb_mode = false;
 	_options.clean_cache = false;
 
-	while ((opt = getopt(argc, argv, "bcdFfg:hin:N:oqrstvZz:")) != -1) {
+	while ((opt = getopt(argc, argv, "bcdFfg:G:hin:N:oqrstvZz:")) != -1) {
 		switch (opt) {
 			case '?':
 				print_usage();
@@ -87,6 +88,14 @@ void parse_options(int argc, char **argv)
 			case 'g':
 				_options.geometry = optarg;
 				break;
+			case 'G':
+				if (sscanf(optarg, "%d", &gamma) <= 0) {
+					fprintf(stderr, "sxiv: invalid argument for option -G: %s\n",
+					        optarg);
+					exit(EXIT_FAILURE);
+				}
+				_options.gamma = gamma;
+				break;
 			case 'h':
 				print_usage();
 				exit(EXIT_SUCCESS);
diff --git a/options.h b/options.h
index 848a6b2..982602f 100644
--- a/options.h
+++ b/options.h
@@ -34,6 +34,7 @@ typedef struct {
 	/* image: */
 	scalemode_t scalemode;
 	float zoom;
+	int gamma;
 
 	/* window: */
 	bool fixed_win;
diff --git a/sxiv.1 b/sxiv.1
index ee42a00..4c29dbf 100644
--- a/sxiv.1
+++ b/sxiv.1
@@ -49,6 +49,9 @@ Set window position and size. See section GEOMETRY SPECIFICATIONS of X(7) for
 more information on
 .IR GEOMETRY .
 .TP
+.BI "\-G " GAMMA
+Set gamma to GAMMA (-32..32).
+.TP
 .BI "\-n " NUM
 Start at picture number NUM.
 .TP
@@ -282,6 +285,16 @@ Flip image horizontally.
 .TP
 .B _
 Flip image vertically.
+.SS Gamma Correction
+.TP
+.B {
+Decrease gamma.
+.TP
+.B }
+Increase gamma.
+.TP
+.B Ctrl-G
+Reset gamma.
 .SS Miscellaneous
 .TP
 .B a