summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKim Woelders <kim@woelders.dk>2021-12-05 22:55:26 +0100
committerKim Woelders <kim@woelders.dk>2021-12-19 14:58:43 +0100
commitf09d3d022a339193a64ded1af5bad081cdce5103 (patch)
treef24ccdadc02624956cc1d320b31aec455c7d98e7
parentfdd6419fe4c6643c0f5bcdd1b2a42e4e12d7b4b7 (diff)
downloadimlib2-f09d3d022a339193a64ded1af5bad081cdce5103.tar.gz
imlib2_view: Add support for multiframe images
-rw-r--r--src/bin/imlib2_view.c138
1 files changed, 123 insertions, 15 deletions
diff --git a/src/bin/imlib2_view.c b/src/bin/imlib2_view.c
index 23f6d8f..029dfde 100644
--- a/src/bin/imlib2_view.c
+++ b/src/bin/imlib2_view.c
@@ -32,6 +32,12 @@ static char opt_progress_granularity = 10;
static char opt_progress_print = 0;
static int opt_progress_delay = 0;
+static Imlib_Frame_Info finfo;
+static bool multiframe = false; /* Image has multiple frames */
+static bool fixedframe = false; /* We have selected single frame */
+static bool animated = false; /* Image has animation sequence */
+static bool animate = false; /* Animation is active */
+
#define Dprintf if (debug) printf
#define Vprintf if (verbose) printf
@@ -158,12 +164,17 @@ progress(Imlib_Image im, char percent, int update_x, int update_y,
int update_w, int update_h)
{
static double scale_x = 0., scale_y = 0.;
- int up_wx, up_wy, up_ww, up_wh;
+ int up_sx, up_sy, up_wx, up_wy, up_ww, up_wh;
if (opt_progress_print)
printf("%s: %3d%% %4d,%4d %4dx%4d\n",
__func__, percent, update_x, update_y, update_w, update_h);
+ imlib_context_set_image(im);
+ imlib_image_get_frame_info(&finfo);
+ multiframe = finfo.frame_count > 1;
+ animated = finfo.frame_flags & IMLIB_IMAGE_ANIMATED;
+
/* first time it's called */
if (image_width == 0)
{
@@ -176,9 +187,8 @@ progress(Imlib_Image im, char percent, int update_x, int update_y,
window_height -= 32;
Dprintf("Screen WxH=%dx%d\n", window_width, window_height);
- imlib_context_set_image(im);
- image_width = imlib_image_get_width();
- image_height = imlib_image_get_height();
+ image_width = fixedframe ? finfo.frame_w : finfo.canvas_w;
+ image_height = fixedframe ? finfo.frame_h : finfo.canvas_h;
Dprintf("Image WxH=%dx%d\n", image_width, image_height);
if (!opt_scale &&
@@ -215,22 +225,36 @@ progress(Imlib_Image im, char percent, int update_x, int update_y,
XMapWindow(disp, win);
XSync(disp, False);
}
+ else
+ {
+ if (finfo.frame_flags & IMLIB_FRAME_CLEAR)
+ {
+ bg_pm_init(0);
+ }
+ }
if (update_w <= 0 || update_h <= 0)
{
- update_x = 0;
- update_y = 0;
- update_w = image_width;
- update_h = image_height;
+ update_x = finfo.frame_x;
+ update_y = finfo.frame_y;
+ update_w = finfo.frame_w;
+ update_h = finfo.frame_h;
}
+ up_sx = update_x;
+ up_sy = update_y;
+ if (multiframe)
+ up_sx = up_sy = 0;
+ if (fixedframe)
+ update_x = update_y = 0;
+
imlib_context_set_anti_alias(0);
imlib_context_set_dither(0);
imlib_context_set_blend(1);
imlib_context_set_drawable(bg_pm);
imlib_context_set_image(bg_im);
imlib_blend_image_onto_image(im, 0,
- update_x, update_y, update_w, update_h,
+ up_sx, up_sy, update_w, update_h,
update_x, update_y, update_w, update_h);
up_wx = SCALE_X(update_x);
@@ -241,7 +265,11 @@ progress(Imlib_Image im, char percent, int update_x, int update_y,
imlib_render_image_part_on_drawable_at_size(update_x, update_y,
update_w, update_h,
up_wx, up_wy, up_ww, up_wh);
- XClearArea(disp, win, up_wx, up_wy, up_ww, up_wh, False);
+
+ if (finfo.frame_flags & IMLIB_FRAME_CLEAR)
+ XClearWindow(disp, win);
+ else
+ XClearArea(disp, win, up_wx, up_wy, up_ww, up_wh, False);
XFlush(disp);
if (opt_progress_delay > 0)
@@ -251,6 +279,42 @@ progress(Imlib_Image im, char percent, int update_x, int update_y,
}
static Imlib_Image
+load_image_frame(const char *name, int frame, int inc)
+{
+ Imlib_Image im;
+
+ if (inc && finfo.frame_count > 0)
+ frame = (finfo.frame_count + frame + inc - 1) % finfo.frame_count + 1;
+
+ im = imlib_load_image_frame(name, frame);
+ if (!im)
+ return im;
+
+ if (!opt_progr)
+ {
+ /* No progress callback - render explicitly */
+ progress(im, 100, 0, 0, 0, 0);
+ }
+
+ /* finfo should now be populated by imlib_image_get_frame_info()
+ * called from progress() callback */
+
+ if (multiframe)
+ {
+ Dprintf(" showing frame %d/%d (x,y=%d,%d, wxh=%dx%d T=%d)\n",
+ finfo.frame_num, finfo.frame_count,
+ finfo.frame_x, finfo.frame_y, finfo.frame_w, finfo.frame_h,
+ finfo.frame_delay);
+ }
+ else
+ {
+ Dprintf(" showing image wxh=%dx%d\n", finfo.frame_w, finfo.frame_h);
+ }
+
+ return im;
+}
+
+static Imlib_Image
load_image(int no, const char *name)
{
Imlib_Image im;
@@ -290,13 +354,29 @@ load_image(int no, const char *name)
}
else
{
- im = imlib_load_image(name);
- if (!opt_progr)
+ char nbuf[4096];
+ const char *s;
+ int frame;
+
+ frame = -1;
+ sscanf(name, "%[^%]%%%n", nbuf, &frame);
+ if (frame > 0)
+ {
+ s = name + frame;
+ frame = atoi(s);
+ animate = false;
+ fixedframe = true;
+ }
+ else
{
- /* No progress callback - render explicitly */
- progress(im, 100, 0, 0, 0, 0);
+ frame = 1;
+ animate = true;
+ fixedframe = false;
}
+ im = load_image_frame(nbuf, frame, 0);
+
+ animate = animate && animated;
}
return im;
@@ -429,6 +509,14 @@ main(int argc, char **argv)
im = NULL;
}
+ if (animate)
+ {
+ usleep(1e3 * finfo.frame_delay);
+ im = load_image_frame(argv[no], finfo.frame_num, 1);
+ if (!XPending(disp))
+ continue;
+ }
+
timeout = 0;
XFlush(disp);
@@ -459,6 +547,13 @@ main(int argc, char **argv)
goto show_next;
case XK_Left:
goto show_prev;
+ case XK_p:
+ animate = animated && !animate;
+ break;
+ case XK_Up:
+ goto show_next_frame;
+ case XK_Down:
+ goto show_prev_frame;
}
break;
case ButtonPress:
@@ -539,9 +634,22 @@ main(int argc, char **argv)
break;
}
break;
+ show_next_frame:
+ inc = 1;
+ goto show_next_prev_frame;
+ show_prev_frame:
+ inc = -1;
+ goto show_next_prev_frame;
+ show_next_prev_frame:
+ if (!multiframe)
+ break;
+ if (!animated)
+ image_width = 0; /* Reset window size */
+ im = load_image_frame(argv[no], finfo.frame_num, inc);
+ break;
}
- if (XPending(disp))
+ if (multiframe || XPending(disp))
continue;
xfd = ConnectionNumber(disp);