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_redraw; | ||||
| extern int timo_delay; | ||||
| 
 | ||||
| int it_quit(arg_t a) { | ||||
| 	cleanup(); | ||||
| @ -148,7 +149,7 @@ int it_last(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) { | ||||
|  | ||||
							
								
								
									
										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 | ||||
| }; | ||||
| 
 | ||||
| /* 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 | ||||
| #ifdef _THUMBS_CONFIG | ||||
| 
 | ||||
|  | ||||
							
								
								
									
										104
									
								
								image.c
									
									
									
									
									
								
							
							
						
						
									
										104
									
								
								image.c
									
									
									
									
									
								
							| @ -32,6 +32,8 @@ | ||||
| #include "util.h" | ||||
| #include "config.h" | ||||
| 
 | ||||
| enum { MIN_GIF_DELAY = 50 }; | ||||
| 
 | ||||
| int zl_cnt; | ||||
| float zoom_min; | ||||
| float zoom_max; | ||||
| @ -44,6 +46,7 @@ void img_init(img_t *img, win_t *win) { | ||||
| 	if (img) { | ||||
| 		img->im = NULL; | ||||
| 		img->multi.cap = img->multi.cnt = 0; | ||||
| 		img->multi.animate = 0; | ||||
| 		img->zoom = options->zoom; | ||||
| 		img->zoom = MAX(img->zoom, zoom_min); | ||||
| 		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 intjump[] = { 8, 8, 4, 2 }; | ||||
| 	int err = 0, transp = -1; | ||||
| 	unsigned int delay = 0; | ||||
| 
 | ||||
| 	if (img->multi.cap == 0) { | ||||
| 		img->multi.cap = 8; | ||||
| 		img->multi.frames = (Imlib_Image**) | ||||
| 		                    s_malloc(sizeof(Imlib_Image*) * img->multi.cap); | ||||
| 		img->multi.frames = (img_frame_t*) | ||||
| 		                    s_malloc(sizeof(img_frame_t) * img->multi.cap); | ||||
| 	} | ||||
| 	img->multi.cnt = 0; | ||||
| 	img->multi.sel = 0; | ||||
| @ -107,6 +111,10 @@ int img_load_gif(img_t *img, const fileinfo_t *file) { | ||||
| 						transp = (int) ext[4]; | ||||
| 					else | ||||
| 						transp = -1; | ||||
| 
 | ||||
| 					delay = 10 * ((unsigned int) ext[3] << 8 | (unsigned int) ext[2]); | ||||
| 					if (delay) | ||||
| 						delay = MAX(delay, MIN_GIF_DELAY); | ||||
| 				} | ||||
| 				ext = NULL; | ||||
| 				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) { | ||||
| 				img->multi.cap *= 2; | ||||
| 				img->multi.frames = (Imlib_Image**) | ||||
| 				img->multi.frames = (img_frame_t*) | ||||
| 				                    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); | ||||
| 
 | ||||
| @ -199,13 +209,15 @@ int img_load_gif(img_t *img, const fileinfo_t *file) { | ||||
| 	if (!err && img->multi.cnt > 1) { | ||||
| 		imlib_context_set_image(img->im); | ||||
| 		imlib_free_image(); | ||||
| 		img->im = img->multi.frames[0]; | ||||
| 		img->im = img->multi.frames[0].im; | ||||
| 		img->multi.animate = GIF_AUTOPLAY; | ||||
| 	} else { | ||||
| 		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(); | ||||
| 		} | ||||
| 		img->multi.cnt = 0; | ||||
| 		img->multi.animate = 0; | ||||
| 	} | ||||
| 
 | ||||
| 	imlib_context_set_image(img->im); | ||||
| @ -256,7 +268,7 @@ void img_close(img_t *img, int decache) { | ||||
| 
 | ||||
| 	if (img->multi.cnt) { | ||||
| 		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(); | ||||
| 		} | ||||
| 		img->multi.cnt = 0; | ||||
| @ -378,27 +390,6 @@ void img_render(img_t *img, win_t *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) { | ||||
| 	if (!img || !img->im || !win) | ||||
| 		return 0; | ||||
| @ -569,3 +560,58 @@ void img_toggle_antialias(img_t *img) { | ||||
| 		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" | ||||
| 
 | ||||
| typedef struct { | ||||
| 	Imlib_Image *im; | ||||
| 	unsigned int delay; | ||||
| } img_frame_t; | ||||
| 
 | ||||
| typedef struct { | ||||
| 	img_frame_t *frames; | ||||
| 	int cap; | ||||
| 	int cnt; | ||||
| 	int sel; | ||||
| 	Imlib_Image **frames; | ||||
| 	unsigned char animate; | ||||
| } multi_img_t; | ||||
| 
 | ||||
| typedef struct { | ||||
| @ -56,8 +62,6 @@ void img_close(img_t*, int); | ||||
| 
 | ||||
| void img_render(img_t*, win_t*); | ||||
| 
 | ||||
| int img_change_frame(img_t*, int); | ||||
| 
 | ||||
| int img_fit_win(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*); | ||||
| 
 | ||||
| int img_frame_navigate(img_t*, int); | ||||
| int img_frame_animate(img_t*, int); | ||||
| 
 | ||||
| #endif /* IMAGE_H */ | ||||
|  | ||||
							
								
								
									
										20
									
								
								main.c
									
									
									
									
									
								
							
							
						
						
									
										20
									
								
								main.c
									
									
									
									
									
								
							| @ -54,6 +54,7 @@ char win_title[TITLE_LEN]; | ||||
| 
 | ||||
| int timo_cursor; | ||||
| int timo_redraw; | ||||
| int timo_adelay; /* multi-frame animation delay time */ | ||||
| 
 | ||||
| void cleanup() { | ||||
| 	static int in = 0; | ||||
| @ -140,6 +141,9 @@ void load_image(int new) { | ||||
| 		filesize = fstats.st_size; | ||||
| 	else | ||||
| 		filesize = 0; | ||||
| 
 | ||||
| 	if (img.multi.cnt && img.multi.animate) | ||||
| 		timo_adelay = img.multi.frames[img.multi.sel].delay; | ||||
| } | ||||
| 
 | ||||
| void update_title() { | ||||
| @ -296,10 +300,12 @@ void run() { | ||||
| 			} else { | ||||
| 				timo_redraw = TO_THUMBS_LOAD; | ||||
| 			} | ||||
| 		} else if (timo_cursor || timo_redraw) { | ||||
| 		} | ||||
| 		 | ||||
| 		if (timo_cursor || timo_redraw || timo_adelay) { | ||||
| 			/* check active timeouts */ | ||||
| 			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); | ||||
| 			xfd = ConnectionNumber(win.env.dpy); | ||||
| 			FD_ZERO(&fds); | ||||
| @ -321,7 +327,15 @@ void run() { | ||||
| 				if (!timo_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; | ||||
| 		} | ||||
| 
 | ||||
|  | ||||
							
								
								
									
										13
									
								
								util.c
									
									
									
									
									
								
							
							
						
						
									
										13
									
								
								util.c
									
									
									
									
									
								
							| @ -87,6 +87,19 @@ void die(const char* fmt, ...) { | ||||
| 	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) { | ||||
| 	const char *units[] = { "", "K", "M", "G" }; | ||||
| 	int i; | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Bert
						Bert