瀏覽代碼

Added support for gif animation

master
Bert 13 年之前
父節點
當前提交
8b3ae5027e
共有 7 個文件被更改,包括 126 次插入36 次删除
  1. +2
    -1
      commands.c
  2. +7
    -0
      config.h
  3. +75
    -29
      image.c
  4. +10
    -3
      image.h
  5. +17
    -3
      main.c
  6. +13
    -0
      util.c
  7. +2
    -0
      util.h

+ 2
- 1
commands.c 查看文件

@@ -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
- 0
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




+ 75
- 29
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;
}

+ 10
- 3
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 */

+ 17
- 3
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
- 0
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
- 0
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*);


||||||
x
 
000:0
Loading…
取消
儲存