Added support for gif animation
This commit is contained in:
parent
a4b90aee20
commit
8b3ae5027e
@ -41,6 +41,7 @@ extern int filecnt, fileidx;
|
|||||||
|
|
||||||
extern int timo_cursor;
|
extern int timo_cursor;
|
||||||
extern int timo_redraw;
|
extern int timo_redraw;
|
||||||
|
extern int timo_delay;
|
||||||
|
|
||||||
int it_quit(arg_t a) {
|
int it_quit(arg_t a) {
|
||||||
cleanup();
|
cleanup();
|
||||||
@ -148,7 +149,7 @@ int it_last(arg_t a) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int i_navigate_frame(arg_t a) {
|
int i_navigate_frame(arg_t a) {
|
||||||
return img_change_frame(&img, (int) a);
|
return img_frame_navigate(&img, (int) a);
|
||||||
}
|
}
|
||||||
|
|
||||||
int it_move(arg_t a) {
|
int it_move(arg_t a) {
|
||||||
|
7
config.h
7
config.h
@ -29,6 +29,13 @@ static const float zoom_levels[] = {
|
|||||||
100.0, 150.0, 200.0, 400.0, 800.0
|
100.0, 150.0, 200.0, 400.0, 800.0
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* default settings for gif images: */
|
||||||
|
enum {
|
||||||
|
GIF_DELAY = 100, /* delay time (in ms) */
|
||||||
|
GIF_AUTOPLAY = 1, /* autoplay when loaded [0/1] */
|
||||||
|
GIF_LOOP = 0 /* endless loop [0/1] */
|
||||||
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
#ifdef _THUMBS_CONFIG
|
#ifdef _THUMBS_CONFIG
|
||||||
|
|
||||||
|
104
image.c
104
image.c
@ -32,6 +32,8 @@
|
|||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
|
enum { MIN_GIF_DELAY = 50 };
|
||||||
|
|
||||||
int zl_cnt;
|
int zl_cnt;
|
||||||
float zoom_min;
|
float zoom_min;
|
||||||
float zoom_max;
|
float zoom_max;
|
||||||
@ -44,6 +46,7 @@ void img_init(img_t *img, win_t *win) {
|
|||||||
if (img) {
|
if (img) {
|
||||||
img->im = NULL;
|
img->im = NULL;
|
||||||
img->multi.cap = img->multi.cnt = 0;
|
img->multi.cap = img->multi.cnt = 0;
|
||||||
|
img->multi.animate = 0;
|
||||||
img->zoom = options->zoom;
|
img->zoom = options->zoom;
|
||||||
img->zoom = MAX(img->zoom, zoom_min);
|
img->zoom = MAX(img->zoom, zoom_min);
|
||||||
img->zoom = MIN(img->zoom, zoom_max);
|
img->zoom = MIN(img->zoom, zoom_max);
|
||||||
@ -72,11 +75,12 @@ int img_load_gif(img_t *img, const fileinfo_t *file) {
|
|||||||
int intoffset[] = { 0, 4, 2, 1 };
|
int intoffset[] = { 0, 4, 2, 1 };
|
||||||
int intjump[] = { 8, 8, 4, 2 };
|
int intjump[] = { 8, 8, 4, 2 };
|
||||||
int err = 0, transp = -1;
|
int err = 0, transp = -1;
|
||||||
|
unsigned int delay = 0;
|
||||||
|
|
||||||
if (img->multi.cap == 0) {
|
if (img->multi.cap == 0) {
|
||||||
img->multi.cap = 8;
|
img->multi.cap = 8;
|
||||||
img->multi.frames = (Imlib_Image**)
|
img->multi.frames = (img_frame_t*)
|
||||||
s_malloc(sizeof(Imlib_Image*) * img->multi.cap);
|
s_malloc(sizeof(img_frame_t) * img->multi.cap);
|
||||||
}
|
}
|
||||||
img->multi.cnt = 0;
|
img->multi.cnt = 0;
|
||||||
img->multi.sel = 0;
|
img->multi.sel = 0;
|
||||||
@ -107,6 +111,10 @@ int img_load_gif(img_t *img, const fileinfo_t *file) {
|
|||||||
transp = (int) ext[4];
|
transp = (int) ext[4];
|
||||||
else
|
else
|
||||||
transp = -1;
|
transp = -1;
|
||||||
|
|
||||||
|
delay = 10 * ((unsigned int) ext[3] << 8 | (unsigned int) ext[2]);
|
||||||
|
if (delay)
|
||||||
|
delay = MAX(delay, MIN_GIF_DELAY);
|
||||||
}
|
}
|
||||||
ext = NULL;
|
ext = NULL;
|
||||||
DGifGetExtensionNext(gif, &ext);
|
DGifGetExtensionNext(gif, &ext);
|
||||||
@ -186,11 +194,13 @@ int img_load_gif(img_t *img, const fileinfo_t *file) {
|
|||||||
|
|
||||||
if (img->multi.cnt == img->multi.cap) {
|
if (img->multi.cnt == img->multi.cap) {
|
||||||
img->multi.cap *= 2;
|
img->multi.cap *= 2;
|
||||||
img->multi.frames = (Imlib_Image**)
|
img->multi.frames = (img_frame_t*)
|
||||||
s_realloc(img->multi.frames,
|
s_realloc(img->multi.frames,
|
||||||
img->multi.cap * sizeof(Imlib_Image*));
|
img->multi.cap * sizeof(img_frame_t));
|
||||||
}
|
}
|
||||||
img->multi.frames[img->multi.cnt++] = im;
|
img->multi.frames[img->multi.cnt].im = im;
|
||||||
|
img->multi.frames[img->multi.cnt].delay = delay ? delay : GIF_DELAY;
|
||||||
|
img->multi.cnt++;
|
||||||
}
|
}
|
||||||
} while (rec != TERMINATE_RECORD_TYPE);
|
} while (rec != TERMINATE_RECORD_TYPE);
|
||||||
|
|
||||||
@ -199,13 +209,15 @@ int img_load_gif(img_t *img, const fileinfo_t *file) {
|
|||||||
if (!err && img->multi.cnt > 1) {
|
if (!err && img->multi.cnt > 1) {
|
||||||
imlib_context_set_image(img->im);
|
imlib_context_set_image(img->im);
|
||||||
imlib_free_image();
|
imlib_free_image();
|
||||||
img->im = img->multi.frames[0];
|
img->im = img->multi.frames[0].im;
|
||||||
|
img->multi.animate = GIF_AUTOPLAY;
|
||||||
} else {
|
} else {
|
||||||
for (i = 0; i < img->multi.cnt; i++) {
|
for (i = 0; i < img->multi.cnt; i++) {
|
||||||
imlib_context_set_image(img->multi.frames[i]);
|
imlib_context_set_image(img->multi.frames[i].im);
|
||||||
imlib_free_image();
|
imlib_free_image();
|
||||||
}
|
}
|
||||||
img->multi.cnt = 0;
|
img->multi.cnt = 0;
|
||||||
|
img->multi.animate = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
imlib_context_set_image(img->im);
|
imlib_context_set_image(img->im);
|
||||||
@ -256,7 +268,7 @@ void img_close(img_t *img, int decache) {
|
|||||||
|
|
||||||
if (img->multi.cnt) {
|
if (img->multi.cnt) {
|
||||||
for (i = 0; i < img->multi.cnt; i++) {
|
for (i = 0; i < img->multi.cnt; i++) {
|
||||||
imlib_context_set_image(img->multi.frames[i]);
|
imlib_context_set_image(img->multi.frames[i].im);
|
||||||
imlib_free_image();
|
imlib_free_image();
|
||||||
}
|
}
|
||||||
img->multi.cnt = 0;
|
img->multi.cnt = 0;
|
||||||
@ -378,27 +390,6 @@ void img_render(img_t *img, win_t *win) {
|
|||||||
win_draw(win);
|
win_draw(win);
|
||||||
}
|
}
|
||||||
|
|
||||||
int img_change_frame(img_t *img, int d) {
|
|
||||||
if (!img || !img->multi.cnt || !d)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
d += img->multi.sel;
|
|
||||||
if (d < 0)
|
|
||||||
d = 0;
|
|
||||||
else if (d >= img->multi.cnt)
|
|
||||||
d = img->multi.cnt - 1;
|
|
||||||
|
|
||||||
img->multi.sel = d;
|
|
||||||
img->im = img->multi.frames[d];
|
|
||||||
|
|
||||||
imlib_context_set_image(img->im);
|
|
||||||
img->w = imlib_image_get_width();
|
|
||||||
img->h = imlib_image_get_height();
|
|
||||||
img->checkpan = 1;
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int img_fit_win(img_t *img, win_t *win) {
|
int img_fit_win(img_t *img, win_t *win) {
|
||||||
if (!img || !img->im || !win)
|
if (!img || !img->im || !win)
|
||||||
return 0;
|
return 0;
|
||||||
@ -569,3 +560,58 @@ void img_toggle_antialias(img_t *img) {
|
|||||||
imlib_context_set_anti_alias(img->aa);
|
imlib_context_set_anti_alias(img->aa);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int img_frame_goto(img_t *img, int n) {
|
||||||
|
if (!img || n < 0 || n >= img->multi.cnt)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (n == img->multi.sel)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
img->multi.sel = n;
|
||||||
|
img->im = img->multi.frames[n].im;
|
||||||
|
|
||||||
|
imlib_context_set_image(img->im);
|
||||||
|
img->w = imlib_image_get_width();
|
||||||
|
img->h = imlib_image_get_height();
|
||||||
|
img->checkpan = 1;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int img_frame_navigate(img_t *img, int d) {
|
||||||
|
if (!img || !img->multi.cnt || !d)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
d += img->multi.sel;
|
||||||
|
if (d < 0)
|
||||||
|
d = 0;
|
||||||
|
else if (d >= img->multi.cnt)
|
||||||
|
d = img->multi.cnt - 1;
|
||||||
|
|
||||||
|
return img_frame_goto(img, d);
|
||||||
|
}
|
||||||
|
|
||||||
|
int img_frame_animate(img_t *img, int restart) {
|
||||||
|
if (!img || !img->multi.cnt)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (!img->multi.animate && !restart)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (restart) {
|
||||||
|
img_frame_goto(img, 0);
|
||||||
|
img->multi.animate = 1;
|
||||||
|
} else if (img->multi.sel + 1 >= img->multi.cnt) {
|
||||||
|
if (!GIF_LOOP) {
|
||||||
|
img->multi.animate = 0;
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
img_frame_goto(img, 0);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
img_frame_goto(img, img->multi.sel + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return img->multi.frames[img->multi.sel].delay;
|
||||||
|
}
|
||||||
|
13
image.h
13
image.h
@ -25,10 +25,16 @@
|
|||||||
#include "window.h"
|
#include "window.h"
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
Imlib_Image *im;
|
||||||
|
unsigned int delay;
|
||||||
|
} img_frame_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
img_frame_t *frames;
|
||||||
int cap;
|
int cap;
|
||||||
int cnt;
|
int cnt;
|
||||||
int sel;
|
int sel;
|
||||||
Imlib_Image **frames;
|
unsigned char animate;
|
||||||
} multi_img_t;
|
} multi_img_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@ -56,8 +62,6 @@ void img_close(img_t*, int);
|
|||||||
|
|
||||||
void img_render(img_t*, win_t*);
|
void img_render(img_t*, win_t*);
|
||||||
|
|
||||||
int img_change_frame(img_t*, int);
|
|
||||||
|
|
||||||
int img_fit_win(img_t*, win_t*);
|
int img_fit_win(img_t*, win_t*);
|
||||||
int img_center(img_t*, win_t*);
|
int img_center(img_t*, win_t*);
|
||||||
|
|
||||||
@ -74,4 +78,7 @@ void img_rotate_right(img_t*, win_t*);
|
|||||||
|
|
||||||
void img_toggle_antialias(img_t*);
|
void img_toggle_antialias(img_t*);
|
||||||
|
|
||||||
|
int img_frame_navigate(img_t*, int);
|
||||||
|
int img_frame_animate(img_t*, int);
|
||||||
|
|
||||||
#endif /* IMAGE_H */
|
#endif /* IMAGE_H */
|
||||||
|
20
main.c
20
main.c
@ -54,6 +54,7 @@ char win_title[TITLE_LEN];
|
|||||||
|
|
||||||
int timo_cursor;
|
int timo_cursor;
|
||||||
int timo_redraw;
|
int timo_redraw;
|
||||||
|
int timo_adelay; /* multi-frame animation delay time */
|
||||||
|
|
||||||
void cleanup() {
|
void cleanup() {
|
||||||
static int in = 0;
|
static int in = 0;
|
||||||
@ -140,6 +141,9 @@ void load_image(int new) {
|
|||||||
filesize = fstats.st_size;
|
filesize = fstats.st_size;
|
||||||
else
|
else
|
||||||
filesize = 0;
|
filesize = 0;
|
||||||
|
|
||||||
|
if (img.multi.cnt && img.multi.animate)
|
||||||
|
timo_adelay = img.multi.frames[img.multi.sel].delay;
|
||||||
}
|
}
|
||||||
|
|
||||||
void update_title() {
|
void update_title() {
|
||||||
@ -296,10 +300,12 @@ void run() {
|
|||||||
} else {
|
} else {
|
||||||
timo_redraw = TO_THUMBS_LOAD;
|
timo_redraw = TO_THUMBS_LOAD;
|
||||||
}
|
}
|
||||||
} else if (timo_cursor || timo_redraw) {
|
}
|
||||||
|
|
||||||
|
if (timo_cursor || timo_redraw || timo_adelay) {
|
||||||
/* check active timeouts */
|
/* check active timeouts */
|
||||||
gettimeofday(&t0, 0);
|
gettimeofday(&t0, 0);
|
||||||
timeout = MIN(timo_cursor + 1, timo_redraw + 1);
|
timeout = min_int_nz(3, timo_cursor, timo_redraw, timo_adelay);
|
||||||
MSEC_TO_TIMEVAL(timeout, &tt);
|
MSEC_TO_TIMEVAL(timeout, &tt);
|
||||||
xfd = ConnectionNumber(win.env.dpy);
|
xfd = ConnectionNumber(win.env.dpy);
|
||||||
FD_ZERO(&fds);
|
FD_ZERO(&fds);
|
||||||
@ -321,7 +327,15 @@ void run() {
|
|||||||
if (!timo_redraw)
|
if (!timo_redraw)
|
||||||
redraw();
|
redraw();
|
||||||
}
|
}
|
||||||
if ((timo_cursor || timo_redraw) && !XPending(win.env.dpy))
|
if (timo_adelay) {
|
||||||
|
timo_adelay = MAX(0, timo_adelay - timeout);
|
||||||
|
if (!timo_adelay) {
|
||||||
|
if ((timo_adelay = img_frame_animate(&img, 0)))
|
||||||
|
redraw();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((timo_cursor || timo_redraw || timo_adelay) &&
|
||||||
|
!XPending(win.env.dpy))
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
13
util.c
13
util.c
@ -87,6 +87,19 @@ void die(const char* fmt, ...) {
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int min_int_nz(int n, ...) {
|
||||||
|
va_list args;
|
||||||
|
int i, a, m = 0;
|
||||||
|
|
||||||
|
va_start(args, n);
|
||||||
|
for (i = 0; i < n; i++) {
|
||||||
|
if ((a = va_arg(args, int)) && (!m || a < m))
|
||||||
|
m = a;
|
||||||
|
}
|
||||||
|
va_end(args);
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
|
||||||
void size_readable(float *size, const char **unit) {
|
void size_readable(float *size, const char **unit) {
|
||||||
const char *units[] = { "", "K", "M", "G" };
|
const char *units[] = { "", "K", "M", "G" };
|
||||||
int i;
|
int i;
|
||||||
|
2
util.h
2
util.h
@ -60,6 +60,8 @@ char* s_strdup(char*);
|
|||||||
void warn(const char*, ...);
|
void warn(const char*, ...);
|
||||||
void die(const char*, ...);
|
void die(const char*, ...);
|
||||||
|
|
||||||
|
int min_int_nz(int, ...);
|
||||||
|
|
||||||
void size_readable(float*, const char**);
|
void size_readable(float*, const char**);
|
||||||
|
|
||||||
char* absolute_path(const char*);
|
char* absolute_path(const char*);
|
||||||
|
Loading…
Reference in New Issue
Block a user