summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile2
-rw-r--r--README.md5
-rw-r--r--commands.c22
-rw-r--r--commands.h1
-rw-r--r--config.def.h11
-rw-r--r--image.c54
-rw-r--r--image.h5
-rw-r--r--main.c13
-rw-r--r--options.c17
-rw-r--r--options.h1
-rw-r--r--sxiv.127
-rw-r--r--thumbs.c49
-rw-r--r--thumbs.h1
13 files changed, 175 insertions, 33 deletions
diff --git a/Makefile b/Makefile
index 754ddce..6c7fd4e 100644
--- a/Makefile
+++ b/Makefile
@@ -1,4 +1,4 @@
-VERSION = git-20131021
+VERSION = git-20131114
PREFIX = /usr/local
MANPREFIX = $(PREFIX)/share/man
diff --git a/README.md b/README.md
index 913deac..23b94f4 100644
--- a/README.md
+++ b/README.md
@@ -74,11 +74,12 @@ of small previews is displayed, making it easy to choose an image to open.
-d Scale all images to 100%, but fit large images into window
-F Use size-hints to make the window fixed/floating
-f Start in fullscreen mode
+ -G GAMMA Set image gamma to GAMMA (-32..32)
-g GEOMETRY Set window position and size
(see section GEOMETRY SPECIFICATIONS of X(7))
-i Read file list from stdin
- -n NUM Start at picture NUM
-N NAME Set X window resource name to NAME
+ -n NUM Start at picture NUM
-o Write list of marked files to stdout when quitting
-q Be quiet, disable warnings
-r Search given directories recursively for images
@@ -108,7 +109,7 @@ of small previews is displayed, making it easy to choose an image to open.
D Remove image from file list and go to next image
m Mark/unmark current image
- M Reverse marked images
+ M Reverse all image marks
N Go [count] marked images forward
P Go [count] marked images backward
diff --git a/commands.c b/commands.c
index 9dbe2c0..49298bf 100644
--- a/commands.c
+++ b/commands.c
@@ -48,7 +48,6 @@ extern win_t win;
extern fileinfo_t *files;
extern int filecnt, fileidx;
-extern int markcnt;
extern int alternate;
extern int prefix;
@@ -61,7 +60,7 @@ bool it_quit(arg_t a)
{
unsigned int i;
- if (options->to_stdout && markcnt > 0) {
+ if (options->to_stdout) {
for (i = 0; i < filecnt; i++) {
if (files[i].marked)
printf("%s\n", files[i].name);
@@ -247,7 +246,8 @@ bool it_toggle_image_mark(arg_t a)
int sel = mode == MODE_IMAGE ? fileidx : tns.sel;
files[sel].marked = !files[sel].marked;
- markcnt += files[sel].marked ? 1 : -1;
+ if (mode == MODE_THUMB)
+ tns_mark(&tns, sel, files[sel].marked);
return true;
}
@@ -255,11 +255,10 @@ bool it_reverse_marks(arg_t a)
{
int i, cnt = mode == MODE_IMAGE ? filecnt : tns.cnt;
- for (i = 0; i < cnt; i++) {
+ for (i = 0; i < cnt; i++)
files[i].marked = !files[i].marked;
- markcnt += files[i].marked ? 1 : -1;
- }
-
+ if (mode == MODE_THUMB)
+ tns.dirty = true;
return true;
}
@@ -486,6 +485,15 @@ bool i_toggle_antialias(arg_t a)
}
}
+bool i_change_gamma(arg_t a)
+{
+ if (mode == MODE_IMAGE) {
+ return img_change_gamma(&img, (long) a);
+ } 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 58bfafb..ba40eed 100644
--- a/commands.h
+++ b/commands.h
@@ -68,6 +68,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 c5e002f..b1e9c02 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
@@ -142,6 +148,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..ee49076 100644
--- a/image.c
+++ b/image.c
@@ -39,11 +39,27 @@ enum { MIN_GIF_DELAY = 25 };
float zoom_min;
float zoom_max;
-int zoomdiff(float z1, float z2)
+static int zoomdiff(float z1, float z2)
{
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)
{
zoom_min = zoom_levels[0] / 100.0;
@@ -67,6 +83,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->gamma = MIN(MAX(options->gamma, -GAMMA_RANGE), GAMMA_RANGE);
}
void exif_auto_orientate(const fileinfo_t *file)
@@ -303,6 +322,8 @@ bool img_load(img_t *img, const fileinfo_t *file)
img_load_gif(img, file);
#endif
+ img_apply_gamma(img);
+
img->w = imlib_image_get_width();
img->h = imlib_image_get_height();
img->scalemode = options->scalemode;
@@ -335,6 +356,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 +730,34 @@ void img_toggle_antialias(img_t *img)
img->dirty = true;
}
+bool img_change_gamma(img_t *img, int d)
+{
+ /* d < 0: decrease gamma
+ * d = 0: reset gamma
+ * d > 0: increase gamma
+ */
+ int gamma;
+
+ if (img == NULL || img->im == NULL)
+ return false;
+
+ if (d == 0)
+ gamma = 0;
+ else if (d < 0)
+ gamma = MAX(-GAMMA_RANGE, img->gamma - 1);
+ else
+ gamma = MIN(+GAMMA_RANGE, img->gamma + 1);
+
+ if (img->gamma != gamma) {
+ img->gamma = gamma;
+ img_apply_gamma(img);
+ img->dirty = true;
+ return true;
+ } else {
+ return false;
+ }
+}
+
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..09322c2 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*);
+bool img_change_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..b1140cb 100644
--- a/main.c
+++ b/main.c
@@ -65,7 +65,6 @@ win_t win;
fileinfo_t *files;
int filecnt, fileidx;
-int markcnt;
int alternate;
int prefix;
@@ -346,7 +345,10 @@ void update_info(void)
ow_info = false;
}
} 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) {
for (fn = 0, i = img.multi.cnt; i > 0; fn++, i /= 10);
n += snprintf(rt + n, rlen - n, "%0*d/%d | ",
@@ -493,6 +495,13 @@ void on_buttonpress(XButtonEvent *bev)
break;
}
break;
+ case Button3:
+ if ((sel = tns_translate(&tns, bev->x, bev->y)) >= 0) {
+ files[sel].marked = !files[sel].marked;
+ tns_mark(&tns, sel, files[sel].marked);
+ redraw();
+ }
+ break;
case Button4:
case Button5:
if (tns_scroll(&tns, bev->button == Button4 ? DIR_UP : DIR_DOWN,
diff --git a/options.c b/options.c
index e47ad37..e4d597c 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 GAMMA] [-g GEOMETRY] [-n NUM] "
"[-N name] [-z ZOOM] FILES...\n");
}
@@ -44,7 +44,8 @@ void print_version(void)
void parse_options(int argc, char **argv)
{
- int opt, t;
+ int opt, t, gamma;
+ char *end;
_options.from_stdin = false;
_options.to_stdout = false;
@@ -53,6 +54,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 +66,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();
@@ -84,6 +86,15 @@ void parse_options(int argc, char **argv)
case 'f':
_options.fullscreen = true;
break;
+ case 'G':
+ gamma = strtol(optarg, &end, 0);
+ if (*end != '\0') {
+ fprintf(stderr, "sxiv: invalid argument for option -G: %s\n",
+ optarg);
+ exit(EXIT_FAILURE);
+ }
+ _options.gamma = gamma;
+ break;
case 'g':
_options.geometry = optarg;
break;
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 f8ad0c1..1fca2dd 100644
--- a/sxiv.1
+++ b/sxiv.1
@@ -4,12 +4,14 @@ sxiv \- Simple X Image Viewer
.SH SYNOPSIS
.B sxiv
.RB [ \-bcdFfhiopqrstvZ ]
+.RB [ \-G
+.IR GAMMA ]
.RB [ \-g
.IR GEOMETRY ]
-.RB [ \-n
-.IR NUM ]
.RB [ \-N
.IR NAME ]
+.RB [ \-n
+.IR NUM ]
.RB [ \-z
.IR ZOOM ]
.IR FILE ...
@@ -44,17 +46,20 @@ size-hints to the window width/height.
.B \-f
Start in fullscreen mode.
.TP
+.BI "\-G " GAMMA
+Set image gamma to GAMMA (-32..32).
+.TP
.BI "\-g " GEOMETRY
Set window position and size. See section GEOMETRY SPECIFICATIONS of X(7) for
more information on
.IR GEOMETRY .
.TP
-.BI "\-n " NUM
-Start at picture number NUM.
-.TP
.BI "\-N " NAME
Set the resource name of sxiv's X window to NAME.
.TP
+.BI "\-n " NUM
+Start at picture number NUM.
+.TP
.B \-h
Print brief usage information to standard output and exit.
.TP
@@ -131,7 +136,7 @@ Remove current image from file list and go to next image.
Mark/unmark the current image.
.TP
.B M
-Reverse marked images.
+Reverse all image marks.
.TP
.B N
Go
@@ -285,6 +290,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
diff --git a/thumbs.c b/thumbs.c
index ec6e5ef..a1ee779 100644
--- a/thumbs.c
+++ b/thumbs.c
@@ -363,6 +363,8 @@ void tns_render(tns_t *tns)
imlib_render_image_part_on_drawable_at_size(0, 0, t->w, t->h,
t->x, t->y, t->w, t->h);
+ if (t->file->marked)
+ tns_mark(tns, tns->first + i, true);
if ((i + 1) % tns->cols == 0) {
x = tns->x;
y += thumb_dim;
@@ -374,20 +376,44 @@ void tns_render(tns_t *tns)
tns_highlight(tns, tns->sel, true);
}
-void tns_highlight(tns_t *tns, int n, bool hl)
+void tns_mark(tns_t *tns, int n, bool mark)
{
- thumb_t *t;
- win_t *win;
- int x, y;
- unsigned long col;
-
if (tns == NULL || tns->thumbs == NULL || tns->win == NULL)
return;
- win = tns->win;
+ if (n >= 0 && n < tns->cnt) {
+ unsigned long col;
+ thumb_t *t = &tns->thumbs[n];
+ win_t *win = tns->win;
+ int x = t->x, y = t->y, w = t->w, h = t->h;
+
+ if (mark || n == tns->sel)
+ col = win->selcol;
+ else if (win->fullscreen)
+ col = win->fscol;
+ else
+ col = win->bgcol;
+
+ win_draw_rect(win, win->pm, x - 4, y - 4, 8, 2, true, 0, col);
+ win_draw_rect(win, win->pm, x - 4, y - 4, 2, 8, true, 0, col);
+ win_draw_rect(win, win->pm, x + w - 4, y - 4, 8, 2, true, 0, col);
+ win_draw_rect(win, win->pm, x + w + 2, y - 4, 2, 8, true, 0, col);
+ win_draw_rect(win, win->pm, x - 4, y + h + 2, 8, 2, true, 0, col);
+ win_draw_rect(win, win->pm, x - 4, y + h - 4, 2, 8, true, 0, col);
+ win_draw_rect(win, win->pm, x + w - 4, y + h + 2, 8, 2, true, 0, col);
+ win_draw_rect(win, win->pm, x + w + 2, y + h - 4, 2, 8, true, 0, col);
+ }
+}
+
+void tns_highlight(tns_t *tns, int n, bool hl)
+{
+ if (tns == NULL || tns->thumbs == NULL || tns->win == NULL)
+ return;
if (n >= 0 && n < tns->cnt) {
- t = &tns->thumbs[n];
+ unsigned long col;
+ thumb_t *t = &tns->thumbs[n];
+ win_t *win = tns->win;
if (hl)
col = win->selcol;
@@ -396,10 +422,11 @@ void tns_highlight(tns_t *tns, int n, bool hl)
else
col = win->bgcol;
- x = t->x - (THUMB_SIZE - t->w) / 2;
- y = t->y - (THUMB_SIZE - t->h) / 2;
- win_draw_rect(win, win->pm, x - 3, y - 3, THUMB_SIZE + 6, THUMB_SIZE + 6,
+ win_draw_rect(win, win->pm, t->x - 3, t->y - 3, t->w + 6, t->h + 6,
false, 2, col);
+
+ if (!hl && t->file->marked)
+ tns_mark(tns, n, true);
}
}
diff --git a/thumbs.h b/thumbs.h
index aa95961..64ae412 100644
--- a/thumbs.h
+++ b/thumbs.h
@@ -59,6 +59,7 @@ void tns_free(tns_t*);
bool tns_load(tns_t*, int, const fileinfo_t*, bool, bool);
void tns_render(tns_t*);
+void tns_mark(tns_t*, int, bool);
void tns_highlight(tns_t*, int, bool);
bool tns_move_selection(tns_t*, direction_t, int);