@@ -474,17 +474,10 @@ 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) | bool i_change_gamma(arg_t a) | ||||
{ | { | ||||
if (mode == MODE_IMAGE) { | if (mode == MODE_IMAGE) { | ||||
long val = (long) a; | return img_change_gamma(&img, (long) a); | ||||
int delta = val > 0 ? 1 : (val < 0 ? -1 : -img.gamma); | |||||
img_set_gamma(&img, img.gamma + delta); | |||||
return true; | |||||
} else { | } else { | ||||
return false; | return false; | ||||
} | } | ||||
@@ -49,8 +49,8 @@ enum { | |||||
/* gamma correction: the user-visible ranges [-GAMMA_RANGE, 0] and | /* gamma correction: the user-visible ranges [-GAMMA_RANGE, 0] and | ||||
* (0, GAMMA_RANGE] are mapped to the ranges [0, 1], and (1, GAMMA_MAX]. | * (0, GAMMA_RANGE] are mapped to the ranges [0, 1], and (1, GAMMA_MAX]. | ||||
* */ | * */ | ||||
static const double GAMMA_MAX = 10.0; | static const double GAMMA_MAX = 10.0; | ||||
static const int GAMMA_RANGE = 32; | static const int GAMMA_RANGE = 32; | ||||
#endif | #endif | ||||
#ifdef _THUMBS_CONFIG | #ifdef _THUMBS_CONFIG | ||||
@@ -150,7 +150,7 @@ static const keymap_t keys[] = { | |||||
/* decrease/increase/reset gamma */ | /* decrease/increase/reset gamma */ | ||||
{ false, XK_braceleft, i_change_gamma, (arg_t) -1 }, | { false, XK_braceleft, i_change_gamma, (arg_t) -1 }, | ||||
{ false, XK_braceright, i_change_gamma, (arg_t) +1 }, | { false, XK_braceright, i_change_gamma, (arg_t) +1 }, | ||||
{ true, XK_G, i_change_gamma, (arg_t) 0 }, | { true, XK_G, i_change_gamma, (arg_t) 0 }, | ||||
/* open current image with given program: */ | /* open current image with given program: */ | ||||
{ true, XK_g, it_open_with, (arg_t) "gimp" }, | { true, XK_g, it_open_with, (arg_t) "gimp" }, | ||||
@@ -39,11 +39,27 @@ enum { MIN_GIF_DELAY = 25 }; | |||||
float zoom_min; | float zoom_min; | ||||
float zoom_max; | float zoom_max; | ||||
int zoomdiff(float z1, float z2) | static int zoomdiff(float z1, float z2) | ||||
{ | { | ||||
return (int) (z1 * 1000.0 - z2 * 1000.0); | return (int) (z1 * 1000.0 - z2 * 1000.0); | ||||
} | } | ||||
static void img_apply_gamma(img_t *img) | |||||
{ | |||||
if (img == NULL || img->im == NULL || img->cmod == NULL) | |||||
return; | |||||
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 + img->gamma * (range / GAMMA_RANGE)); | |||||
} | |||||
} | |||||
void img_init(img_t *img, win_t *win) | void img_init(img_t *img, win_t *win) | ||||
{ | { | ||||
zoom_min = zoom_levels[0] / 100.0; | zoom_min = zoom_levels[0] / 100.0; | ||||
@@ -69,7 +85,7 @@ void img_init(img_t *img, win_t *win) | |||||
img->multi.animate = false; | img->multi.animate = false; | ||||
img->cmod = imlib_create_color_modifier(); | img->cmod = imlib_create_color_modifier(); | ||||
img_set_gamma(img, options->gamma); | img->gamma = options->gamma; | ||||
} | } | ||||
void exif_auto_orientate(const fileinfo_t *file) | void exif_auto_orientate(const fileinfo_t *file) | ||||
@@ -306,7 +322,7 @@ bool img_load(img_t *img, const fileinfo_t *file) | |||||
img_load_gif(img, file); | img_load_gif(img, file); | ||||
#endif | #endif | ||||
img_set_gamma(img, img->gamma); | img_apply_gamma(img); | ||||
img->w = imlib_image_get_width(); | img->w = imlib_image_get_width(); | ||||
img->h = imlib_image_get_height(); | img->h = imlib_image_get_height(); | ||||
@@ -714,25 +730,31 @@ void img_toggle_antialias(img_t *img) | |||||
img->dirty = true; | img->dirty = true; | ||||
} | } | ||||
void img_set_gamma(img_t *img, int gamma) | bool img_change_gamma(img_t *img, int d) | ||||
{ | { | ||||
if (img == NULL) | /* d < 0: decrease gamma | ||||
return; | * d = 0: reset gamma | ||||
* d > 0: increase gamma | |||||
*/ | |||||
int gamma; | |||||
img->gamma = MIN(MAX(gamma, -GAMMA_RANGE), GAMMA_RANGE); | if (img == NULL || img->im == NULL) | ||||
return false; | |||||
if (img->im && img->cmod) { | if (d == 0) | ||||
if (img->gamma == 0) { | gamma = 0; | ||||
imlib_context_set_color_modifier(NULL); | else if (d < 0) | ||||
} else { | gamma = MAX(-GAMMA_RANGE, img->gamma - 1); | ||||
double range = img->gamma <= 0 ? 1.0 : GAMMA_MAX - 1.0; | else | ||||
imlib_context_set_color_modifier(img->cmod); | gamma = MIN(+GAMMA_RANGE, img->gamma + 1); | ||||
imlib_reset_color_modifier(); | if (img->gamma != gamma) { | ||||
imlib_modify_color_modifier_gamma( | img->gamma = gamma; | ||||
1.0 + (double) img->gamma | img_apply_gamma(img); | ||||
* (range / (double) GAMMA_RANGE)); | |||||
} | |||||
img->dirty = true; | img->dirty = true; | ||||
return true; | |||||
} else { | |||||
return false; | |||||
} | } | ||||
} | } | ||||
@@ -84,7 +84,7 @@ void img_flip(img_t*, flipdir_t); | |||||
void img_toggle_antialias(img_t*); | void img_toggle_antialias(img_t*); | ||||
void img_set_gamma(img_t*, int); | bool img_change_gamma(img_t*, int); | ||||
bool img_frame_navigate(img_t*, int); | bool img_frame_navigate(img_t*, int); | ||||
bool img_frame_animate(img_t*, bool); | bool img_frame_animate(img_t*, bool); | ||||
@@ -345,14 +345,15 @@ void update_info(void) | |||||
ow_info = false; | ow_info = false; | ||||
} | } | ||||
} else { | } else { | ||||
n = snprintf(rt, rlen, "%s%3d%% | ", mark, (int) (img.zoom * 100.0)); | n = snprintf(rt, rlen, "%s", mark); | ||||
if (img.gamma != 0) | |||||
n += snprintf(rt + n, rlen - n, "G%+d | ", img.gamma); | |||||
n += snprintf(rt + n, rlen - n, "%3d%% | ", (int) (img.zoom * 100.0)); | |||||
if (img.multi.cnt > 0) { | if (img.multi.cnt > 0) { | ||||
for (fn = 0, i = img.multi.cnt; i > 0; fn++, i /= 10); | for (fn = 0, i = img.multi.cnt; i > 0; fn++, i /= 10); | ||||
n += snprintf(rt + n, rlen - n, "%0*d/%d | ", | n += snprintf(rt + n, rlen - n, "%0*d/%d | ", | ||||
fn, img.multi.sel + 1, img.multi.cnt); | 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); | n += snprintf(rt + n, rlen - n, "%0*d/%d", fw, sel + 1, filecnt); | ||||
ow_info = info.script == NULL; | ow_info = info.script == NULL; | ||||
} | } | ||||
@@ -33,7 +33,7 @@ const options_t *options = (const options_t*) &_options; | |||||
void print_usage(void) | void print_usage(void) | ||||
{ | { | ||||
printf("usage: sxiv [-bcdFfhioqrstvZ] [-g GEOMETRY] [-G GAMMA] [-n NUM] " | printf("usage: sxiv [-bcdFfhioqrstvZ] [-G GAMMA] [-g GEOMETRY] [-n NUM] " | ||||
"[-N name] [-z ZOOM] FILES...\n"); | "[-N name] [-z ZOOM] FILES...\n"); | ||||
} | } | ||||
@@ -45,6 +45,7 @@ void print_version(void) | |||||
void parse_options(int argc, char **argv) | void parse_options(int argc, char **argv) | ||||
{ | { | ||||
int opt, t, gamma; | int opt, t, gamma; | ||||
char *end; | |||||
_options.from_stdin = false; | _options.from_stdin = false; | ||||
_options.to_stdout = false; | _options.to_stdout = false; | ||||
@@ -65,7 +66,7 @@ void parse_options(int argc, char **argv) | |||||
_options.thumb_mode = false; | _options.thumb_mode = false; | ||||
_options.clean_cache = false; | _options.clean_cache = false; | ||||
while ((opt = getopt(argc, argv, "bcdFfg:G:hin:N:oqrstvZz:")) != -1) { | while ((opt = getopt(argc, argv, "bcdFfG:g:hin:N:oqrstvZz:")) != -1) { | ||||
switch (opt) { | switch (opt) { | ||||
case '?': | case '?': | ||||
print_usage(); | print_usage(); | ||||
@@ -85,17 +86,18 @@ void parse_options(int argc, char **argv) | |||||
case 'f': | case 'f': | ||||
_options.fullscreen = true; | _options.fullscreen = true; | ||||
break; | break; | ||||
case 'g': | |||||
_options.geometry = optarg; | |||||
break; | |||||
case 'G': | case 'G': | ||||
if (sscanf(optarg, "%d", &gamma) <= 0) { | gamma = strtol(optarg, &end, 0); | ||||
if (*end != '\0') { | |||||
fprintf(stderr, "sxiv: invalid argument for option -G: %s\n", | fprintf(stderr, "sxiv: invalid argument for option -G: %s\n", | ||||
optarg); | optarg); | ||||
exit(EXIT_FAILURE); | exit(EXIT_FAILURE); | ||||
} | } | ||||
_options.gamma = gamma; | _options.gamma = gamma; | ||||
break; | break; | ||||
case 'g': | |||||
_options.geometry = optarg; | |||||
break; | |||||
case 'h': | case 'h': | ||||
print_usage(); | print_usage(); | ||||
exit(EXIT_SUCCESS); | exit(EXIT_SUCCESS); | ||||
@@ -4,12 +4,14 @@ sxiv \- Simple X Image Viewer | |||||
.SH SYNOPSIS | .SH SYNOPSIS | ||||
.B sxiv | .B sxiv | ||||
.RB [ \-bcdFfhiopqrstvZ ] | .RB [ \-bcdFfhiopqrstvZ ] | ||||
.RB [ \-G | |||||
.IR GAMMA ] | |||||
.RB [ \-g | .RB [ \-g | ||||
.IR GEOMETRY ] | .IR GEOMETRY ] | ||||
.RB [ \-n | |||||
.IR NUM ] | |||||
.RB [ \-N | .RB [ \-N | ||||
.IR NAME ] | .IR NAME ] | ||||
.RB [ \-n | |||||
.IR NUM ] | |||||
.RB [ \-z | .RB [ \-z | ||||
.IR ZOOM ] | .IR ZOOM ] | ||||
.IR FILE ... | .IR FILE ... | ||||
@@ -44,20 +46,20 @@ size-hints to the window width/height. | |||||
.B \-f | .B \-f | ||||
Start in fullscreen mode. | Start in fullscreen mode. | ||||
.TP | .TP | ||||
.BI "\-G " GAMMA | |||||
Set image gamma to GAMMA (-32..32). | |||||
.TP | |||||
.BI "\-g " GEOMETRY | .BI "\-g " GEOMETRY | ||||
Set window position and size. See section GEOMETRY SPECIFICATIONS of X(7) for | Set window position and size. See section GEOMETRY SPECIFICATIONS of X(7) for | ||||
more information on | more information on | ||||
.IR GEOMETRY . | .IR GEOMETRY . | ||||
.TP | .TP | ||||
.BI "\-G " GAMMA | .BI "\-N " NAME | ||||
Set gamma to GAMMA (-32..32). | Set the resource name of sxiv's X window to NAME. | ||||
.TP | .TP | ||||
.BI "\-n " NUM | .BI "\-n " NUM | ||||
Start at picture number NUM. | Start at picture number NUM. | ||||
.TP | .TP | ||||
.BI "\-N " NAME | |||||
Set the resource name of sxiv's X window to NAME. | |||||
.TP | |||||
.B \-h | .B \-h | ||||
Print brief usage information to standard output and exit. | Print brief usage information to standard output and exit. | ||||
.TP | .TP | ||||