From 5e481912ec983be89f10cbbb21561ed7cc898027 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bert=20M=C3=BCnnich?= Date: Fri, 25 Jul 2014 22:52:31 +0200 Subject: [PATCH] Revised handling of GIF animations - New option `-a`: Play animations at startup - Ctrl-Space toggles animation for all GIF files - Infinite loop for all animations --- Makefile | 2 +- README.md | 3 ++- commands.c | 12 ++++++++---- config.def.h | 7 ------- image.c | 43 +++++++++++++------------------------------ image.h | 2 -- options.c | 8 ++++++-- options.h | 1 + sxiv.1 | 7 +++++-- 9 files changed, 36 insertions(+), 49 deletions(-) diff --git a/Makefile b/Makefile index 8bd57ab..190caf8 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -VERSION = git-20140723 +VERSION = git-20140725 PREFIX = /usr/local MANPREFIX = $(PREFIX)/share/man diff --git a/README.md b/README.md index 90ccec9..ccecbbe 100644 --- a/README.md +++ b/README.md @@ -68,6 +68,7 @@ of small previews is displayed, making it easy to choose an image to open. **Command line options:** + -a Play animations of multi-frame images -b Do not show info bar on bottom of window -c Remove all orphaned cache files from thumbnail cache and exit -f Start in fullscreen mode @@ -117,7 +118,7 @@ of small previews is displayed, making it easy to choose an image to open. p,Backspace Go [count] images backward [,] Go [count] * 10 images backward/forward Ctrl-n,p Go to the next/previous frame of a multi-frame image - Ctrl-Space Play/pause animation of a multi-frame image + Ctrl-Space Play/stop animations of multi-frame images h,j,k,l Scroll image 1/5 of window width/height or [count] pixels left/down/up/right (also with arrow keys) H,J,K,L Scroll to left/bottom/top/right image edge diff --git a/commands.c b/commands.c index cfcd1b1..41e59e8 100644 --- a/commands.c +++ b/commands.c @@ -282,13 +282,17 @@ bool ci_navigate_frame(arg_t a) bool ci_toggle_animation(arg_t a) { + bool dirty = false; + + img.multi.animate = !img.multi.animate; + if (img.multi.animate) { - reset_timeout(animate); - img.multi.animate = false; - } else if (img_frame_animate(&img, true)) { + dirty = img_frame_animate(&img, true); set_timeout(animate, img.multi.frames[img.multi.sel].delay, true); + } else { + reset_timeout(animate); } - return true; + return dirty; } bool ci_scroll(arg_t a) diff --git a/config.def.h b/config.def.h index 2742e65..6f355b5 100644 --- a/config.def.h +++ b/config.def.h @@ -34,13 +34,6 @@ static const float zoom_levels[] = { /* default slideshow delay (in sec, overwritten via -S option): */ enum { SLIDESHOW_DELAY = 5 }; -/* default settings for multi-frame gif images: */ -enum { - GIF_DELAY = 100, /* delay time (in ms) */ - GIF_AUTOPLAY = 1, /* autoplay when loaded [0/1] */ - GIF_LOOP = 0 /* loop? [0: no, 1: endless, -1: as specified in file] */ -}; - /* gamma correction: the user-visible ranges [-GAMMA_RANGE, 0] and * (0, GAMMA_RANGE] are mapped to the ranges [0, 1], and (1, GAMMA_MAX]. * */ diff --git a/image.c b/image.c index 9754e7a..d24cdd2 100644 --- a/image.c +++ b/image.c @@ -35,7 +35,7 @@ #if HAVE_GIFLIB #include -enum { MIN_GIF_DELAY = 25 }; +enum { DEF_GIF_DELAY = 75 }; #endif float zoom_min; @@ -85,8 +85,8 @@ void img_init(img_t *img, win_t *win) img->aa = ANTI_ALIAS; img->alpha = ALPHA_LAYER; img->multi.cap = img->multi.cnt = 0; - img->multi.animate = false; - img->multi.length = img->multi.repeat = 0; + img->multi.animate = options->animate; + img->multi.length = 0; img->cmod = imlib_create_color_modifier(); img->gamma = MIN(MAX(options->gamma, -GAMMA_RANGE), GAMMA_RANGE); @@ -160,7 +160,7 @@ bool img_load_gif(img_t *img, const fileinfo_t *file) s_malloc(sizeof(img_frame_t) * img->multi.cap); } img->multi.cnt = img->multi.sel = 0; - img->multi.length = img->multi.repeat = 0; + img->multi.length = 0; #if defined(GIFLIB_MAJOR) && GIFLIB_MAJOR >= 5 gif = DGifOpenFileName(file->path, NULL); @@ -194,16 +194,7 @@ bool img_load_gif(img_t *img, const fileinfo_t *file) transp = -1; delay = 10 * ((unsigned int) ext[3] << 8 | (unsigned int) ext[2]); - if (delay) - delay = MAX(delay, MIN_GIF_DELAY); - disposal = (unsigned int) ext[1] >> 2 & 0x7; - } else if (ext_code == APPLICATION_EXT_FUNC_CODE) { - if (ext[0] == 11 && memcmp(ext+1, "NETSCAPE2.0", 11) == 0) { - DGifGetExtensionNext(gif, &ext); - if (ext && ext[0] == 3 && ext[1] == 1) - img->multi.repeat = ((int) ext[3] << 8 | (int) ext[2]) - 1; - } } ext = NULL; DGifGetExtensionNext(gif, &ext); @@ -289,7 +280,7 @@ bool img_load_gif(img_t *img, const fileinfo_t *file) img->multi.cap * sizeof(img_frame_t)); } img->multi.frames[img->multi.cnt].im = im; - img->multi.frames[img->multi.cnt].delay = delay ? delay : GIF_DELAY; + img->multi.frames[img->multi.cnt].delay = delay > 0 ? delay : DEF_GIF_DELAY; img->multi.length += img->multi.frames[img->multi.cnt].delay; img->multi.cnt++; } @@ -308,12 +299,10 @@ bool img_load_gif(img_t *img, const fileinfo_t *file) imlib_context_set_image(img->im); imlib_free_image(); img->im = img->multi.frames[0].im; - img->multi.animate = GIF_AUTOPLAY; } else if (img->multi.cnt == 1) { imlib_context_set_image(img->multi.frames[0].im); imlib_free_image(); img->multi.cnt = 0; - img->multi.animate = false; } imlib_context_set_image(img->im); @@ -841,21 +830,15 @@ bool img_frame_animate(img_t *img, bool restart) return false; if (img->multi.sel + 1 >= img->multi.cnt) { - if (restart || GIF_LOOP == 1) { - img_frame_goto(img, 0); - } else if (GIF_LOOP == -1 && img->multi.repeat != 0) { - if (img->multi.repeat > 0) - img->multi.repeat--; - img_frame_goto(img, 0); - } else { - img->multi.animate = false; - return false; - } + img_frame_goto(img, 0); + img->dirty = true; + return true; } else if (!restart) { img_frame_goto(img, img->multi.sel + 1); + img->dirty = true; + return true; + } else { + return false; } - img->multi.animate = true; - img->dirty = true; - - return true; } + diff --git a/image.h b/image.h index e662cc7..0eb5020 100644 --- a/image.h +++ b/image.h @@ -36,7 +36,6 @@ typedef struct { int sel; bool animate; int length; - int repeat; } multi_img_t; typedef struct { @@ -51,7 +50,6 @@ typedef struct { scalemode_t scalemode; float zoom; - bool re; bool checkpan; bool dirty; bool aa; diff --git a/options.c b/options.c index 47fe21a..403785c 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 [-bcfhioqrtvZ] [-G GAMMA] [-g GEOMETRY] [-n NUM] " + printf("usage: sxiv [-abcfhioqrtvZ] [-G GAMMA] [-g GEOMETRY] [-n NUM] " "[-N NAME] [-S DELAY] [-s MODE] [-z ZOOM] FILES...\n"); } @@ -55,6 +55,7 @@ void parse_options(int argc, char **argv) _options.scalemode = SCALE_DOWN; _options.zoom = 1.0; + _options.animate = false; _options.gamma = 0; _options.slideshow = 0; @@ -67,11 +68,14 @@ void parse_options(int argc, char **argv) _options.thumb_mode = false; _options.clean_cache = false; - while ((opt = getopt(argc, argv, "bcfG:g:hin:N:oqrS:s:tvZz:")) != -1) { + while ((opt = getopt(argc, argv, "abcfG:g:hin:N:oqrS:s:tvZz:")) != -1) { switch (opt) { case '?': print_usage(); exit(EXIT_FAILURE); + case 'a': + _options.animate = true; + break; case 'b': _options.hide_bar = true; break; diff --git a/options.h b/options.h index e3d81ca..25abf16 100644 --- a/options.h +++ b/options.h @@ -34,6 +34,7 @@ typedef struct { /* image: */ scalemode_t scalemode; float zoom; + bool animate; int gamma; int slideshow; diff --git a/sxiv.1 b/sxiv.1 index a238282..0ed3164 100644 --- a/sxiv.1 +++ b/sxiv.1 @@ -3,7 +3,7 @@ sxiv \- Simple X Image Viewer .SH SYNOPSIS .B sxiv -.RB [ \-bcfhioqrtvZ ] +.RB [ \-abcfhioqrtvZ ] .RB [ \-G .IR GAMMA ] .RB [ \-g @@ -31,6 +31,9 @@ Please note, that the fullscreen mode requires an EWMH/NetWM compliant window manager. .SH OPTIONS .TP +.B \-a +Play animations of multi-frame images. +.TP .B \-b Do not show info bar on bottom of window. .TP @@ -208,7 +211,7 @@ Go to the next frame of a multi-frame image. Go to the previous frame of a multi-frame image. .TP .B Ctrl-Space -Play/pause animation of a multi-frame image. +Play/stop animations of multi-frame images. .SS Panning .TP .BR h ", " Left