Krolyxon
Commit 8b3ae50

Branches

Refs →

nsxiv8b3ae50

Added support for gif animation

Author
Bert
Date
2011-08-18 16:05 +0200
Committer
Bert · 2011-08-19 15:22 +0200
Parent
a4b90ae
Commit
8b3ae5027e9490bd7edfeea3d3cd2fbc5ec4beaf

+126 −36

7 files changed

  1. M commands.c +2 −1
  2. M config.h +7 −0
  3. M image.c +75 −29
  4. M image.h +10 −3
  5. M main.c +17 −3
  6. M util.c +13 −0
  7. M util.h +2 −0
M commands.c View
@@ -41,6 +41,7 @@ extern int filecnt, fileidx;
4141
4242 extern int timo_cursor;
4343 extern int timo_redraw;
44+extern int timo_delay;
4445
4546 int it_quit(arg_t a) {
4647 cleanup();
@@ -148,7 +149,7 @@ int it_last(arg_t a) {
148149 }
149150
150151 int i_navigate_frame(arg_t a) {
151− return img_change_frame(&img, (int) a);
152+ return img_frame_navigate(&img, (int) a);
152153 }
153154
154155 int it_move(arg_t a) {
M config.h View
@@ -29,6 +29,13 @@ static const float zoom_levels[] = {
2929 100.0, 150.0, 200.0, 400.0, 800.0
3030 };
3131
32+/* default settings for gif images: */
33+enum {
34+ GIF_DELAY = 100, /* delay time (in ms) */
35+ GIF_AUTOPLAY = 1, /* autoplay when loaded [0/1] */
36+ GIF_LOOP = 0 /* endless loop [0/1] */
37+};
38+
3239 #endif
3340 #ifdef _THUMBS_CONFIG
3441
M image.c View
@@ -32,6 +32,8 @@
3232 #include "util.h"
3333 #include "config.h"
3434
35+enum { MIN_GIF_DELAY = 50 };
36+
3537 int zl_cnt;
3638 float zoom_min;
3739 float zoom_max;
@@ -44,6 +46,7 @@ void img_init(img_t *img, win_t *win) {
4446 if (img) {
4547 img->im = NULL;
4648 img->multi.cap = img->multi.cnt = 0;
49+ img->multi.animate = 0;
4750 img->zoom = options->zoom;
4851 img->zoom = MAX(img->zoom, zoom_min);
4952 img->zoom = MIN(img->zoom, zoom_max);
@@ -72,11 +75,12 @@ int img_load_gif(img_t *img, const fileinfo_t *file) {
7275 int intoffset[] = { 0, 4, 2, 1 };
7376 int intjump[] = { 8, 8, 4, 2 };
7477 int err = 0, transp = -1;
78+ unsigned int delay = 0;
7579
7680 if (img->multi.cap == 0) {
7781 img->multi.cap = 8;
78− img->multi.frames = (Imlib_Image**)
79− s_malloc(sizeof(Imlib_Image*) * img->multi.cap);
82+ img->multi.frames = (img_frame_t*)
83+ s_malloc(sizeof(img_frame_t) * img->multi.cap);
8084 }
8185 img->multi.cnt = 0;
8286 img->multi.sel = 0;
@@ -107,6 +111,10 @@ int img_load_gif(img_t *img, const fileinfo_t *file) {
107111 transp = (int) ext[4];
108112 else
109113 transp = -1;
114+
115+ delay = 10 * ((unsigned int) ext[3] << 8 | (unsigned int) ext[2]);
116+ if (delay)
117+ delay = MAX(delay, MIN_GIF_DELAY);
110118 }
111119 ext = NULL;
112120 DGifGetExtensionNext(gif, &ext);
@@ -186,11 +194,13 @@ int img_load_gif(img_t *img, const fileinfo_t *file) {
186194
187195 if (img->multi.cnt == img->multi.cap) {
188196 img->multi.cap *= 2;
189− img->multi.frames = (Imlib_Image**)
197+ img->multi.frames = (img_frame_t*)
190198 s_realloc(img->multi.frames,
191− img->multi.cap * sizeof(Imlib_Image*));
199+ img->multi.cap * sizeof(img_frame_t));
192200 }
193− img->multi.frames[img->multi.cnt++] = im;
201+ img->multi.frames[img->multi.cnt].im = im;
202+ img->multi.frames[img->multi.cnt].delay = delay ? delay : GIF_DELAY;
203+ img->multi.cnt++;
194204 }
195205 } while (rec != TERMINATE_RECORD_TYPE);
196206
@@ -199,13 +209,15 @@ int img_load_gif(img_t *img, const fileinfo_t *file) {
199209 if (!err && img->multi.cnt > 1) {
200210 imlib_context_set_image(img->im);
201211 imlib_free_image();
202− img->im = img->multi.frames[0];
212+ img->im = img->multi.frames[0].im;
213+ img->multi.animate = GIF_AUTOPLAY;
203214 } else {
204215 for (i = 0; i < img->multi.cnt; i++) {
205− imlib_context_set_image(img->multi.frames[i]);
216+ imlib_context_set_image(img->multi.frames[i].im);
206217 imlib_free_image();
207218 }
208219 img->multi.cnt = 0;
220+ img->multi.animate = 0;
209221 }
210222
211223 imlib_context_set_image(img->im);
@@ -256,7 +268,7 @@ void img_close(img_t *img, int decache) {
256268
257269 if (img->multi.cnt) {
258270 for (i = 0; i < img->multi.cnt; i++) {
259− imlib_context_set_image(img->multi.frames[i]);
271+ imlib_context_set_image(img->multi.frames[i].im);
260272 imlib_free_image();
261273 }
262274 img->multi.cnt = 0;
@@ -378,27 +390,6 @@ void img_render(img_t *img, win_t *win) {
378390 win_draw(win);
379391 }
380392
381−int img_change_frame(img_t *img, int d) {
382− if (!img || !img->multi.cnt || !d)
383− return 0;
384−
385− d += img->multi.sel;
386− if (d < 0)
387− d = 0;
388− else if (d >= img->multi.cnt)
389− d = img->multi.cnt - 1;
390−
391− img->multi.sel = d;
392− img->im = img->multi.frames[d];
393−
394− imlib_context_set_image(img->im);
395− img->w = imlib_image_get_width();
396− img->h = imlib_image_get_height();
397− img->checkpan = 1;
398−
399− return 1;
400−}
401−
402393 int img_fit_win(img_t *img, win_t *win) {
403394 if (!img || !img->im || !win)
404395 return 0;
@@ -569,3 +560,58 @@ void img_toggle_antialias(img_t *img) {
569560 imlib_context_set_anti_alias(img->aa);
570561 }
571562 }
563+
564+int img_frame_goto(img_t *img, int n) {
565+ if (!img || n < 0 || n >= img->multi.cnt)
566+ return 0;
567+
568+ if (n == img->multi.sel)
569+ return 0;
570+
571+ img->multi.sel = n;
572+ img->im = img->multi.frames[n].im;
573+
574+ imlib_context_set_image(img->im);
575+ img->w = imlib_image_get_width();
576+ img->h = imlib_image_get_height();
577+ img->checkpan = 1;
578+
579+ return 1;
580+}
581+
582+int img_frame_navigate(img_t *img, int d) {
583+ if (!img || !img->multi.cnt || !d)
584+ return 0;
585+
586+ d += img->multi.sel;
587+ if (d < 0)
588+ d = 0;
589+ else if (d >= img->multi.cnt)
590+ d = img->multi.cnt - 1;
591+
592+ return img_frame_goto(img, d);
593+}
594+
595+int img_frame_animate(img_t *img, int restart) {
596+ if (!img || !img->multi.cnt)
597+ return 0;
598+
599+ if (!img->multi.animate && !restart)
600+ return 0;
601+
602+ if (restart) {
603+ img_frame_goto(img, 0);
604+ img->multi.animate = 1;
605+ } else if (img->multi.sel + 1 >= img->multi.cnt) {
606+ if (!GIF_LOOP) {
607+ img->multi.animate = 0;
608+ return 0;
609+ } else {
610+ img_frame_goto(img, 0);
611+ }
612+ } else {
613+ img_frame_goto(img, img->multi.sel + 1);
614+ }
615+
616+ return img->multi.frames[img->multi.sel].delay;
617+}
M image.h View
@@ -25,10 +25,16 @@
2525 #include "window.h"
2626
2727 typedef struct {
28+ Imlib_Image *im;
29+ unsigned int delay;
30+} img_frame_t;
31+
32+typedef struct {
33+ img_frame_t *frames;
2834 int cap;
2935 int cnt;
3036 int sel;
31− Imlib_Image **frames;
37+ unsigned char animate;
3238 } multi_img_t;
3339
3440 typedef struct {
@@ -56,8 +62,6 @@ void img_close(img_t*, int);
5662
5763 void img_render(img_t*, win_t*);
5864
59−int img_change_frame(img_t*, int);
60−
6165 int img_fit_win(img_t*, win_t*);
6266 int img_center(img_t*, win_t*);
6367
@@ -74,4 +78,7 @@ void img_rotate_right(img_t*, win_t*);
7478
7579 void img_toggle_antialias(img_t*);
7680
81+int img_frame_navigate(img_t*, int);
82+int img_frame_animate(img_t*, int);
83+
7784 #endif /* IMAGE_H */
M main.c View
@@ -54,6 +54,7 @@ char win_title[TITLE_LEN];
5454
5555 int timo_cursor;
5656 int timo_redraw;
57+int timo_adelay; /* multi-frame animation delay time */
5758
5859 void cleanup() {
5960 static int in = 0;
@@ -140,6 +141,9 @@ void load_image(int new) {
140141 filesize = fstats.st_size;
141142 else
142143 filesize = 0;
144+
145+ if (img.multi.cnt && img.multi.animate)
146+ timo_adelay = img.multi.frames[img.multi.sel].delay;
143147 }
144148
145149 void update_title() {
@@ -296,10 +300,12 @@ void run() {
296300 } else {
297301 timo_redraw = TO_THUMBS_LOAD;
298302 }
299− } else if (timo_cursor || timo_redraw) {
303+ }
304+
305+ if (timo_cursor || timo_redraw || timo_adelay) {
300306 /* check active timeouts */
301307 gettimeofday(&t0, 0);
302− timeout = MIN(timo_cursor + 1, timo_redraw + 1);
308+ timeout = min_int_nz(3, timo_cursor, timo_redraw, timo_adelay);
303309 MSEC_TO_TIMEVAL(timeout, &tt);
304310 xfd = ConnectionNumber(win.env.dpy);
305311 FD_ZERO(&fds);
@@ -321,7 +327,15 @@ void run() {
321327 if (!timo_redraw)
322328 redraw();
323329 }
324− if ((timo_cursor || timo_redraw) && !XPending(win.env.dpy))
330+ if (timo_adelay) {
331+ timo_adelay = MAX(0, timo_adelay - timeout);
332+ if (!timo_adelay) {
333+ if ((timo_adelay = img_frame_animate(&img, 0)))
334+ redraw();
335+ }
336+ }
337+ if ((timo_cursor || timo_redraw || timo_adelay) &&
338+ !XPending(win.env.dpy))
325339 continue;
326340 }
327341
M util.c View
@@ -87,6 +87,19 @@ void die(const char* fmt, ...) {
8787 exit(1);
8888 }
8989
90+int min_int_nz(int n, ...) {
91+ va_list args;
92+ int i, a, m = 0;
93+
94+ va_start(args, n);
95+ for (i = 0; i < n; i++) {
96+ if ((a = va_arg(args, int)) && (!m || a < m))
97+ m = a;
98+ }
99+ va_end(args);
100+ return m;
101+}
102+
90103 void size_readable(float *size, const char **unit) {
91104 const char *units[] = { "", "K", "M", "G" };
92105 int i;
M util.h View
@@ -60,6 +60,8 @@ char* s_strdup(char*);
6060 void warn(const char*, ...);
6161 void die(const char*, ...);
6262
63+int min_int_nz(int, ...);
64+
6365 void size_readable(float*, const char**);
6466
6567 char* absolute_path(const char*);