diff --git a/gdk-pixbuf/ChangeLog b/gdk-pixbuf/ChangeLog index aeaabc876f..2229cb01f1 100644 --- a/gdk-pixbuf/ChangeLog +++ b/gdk-pixbuf/ChangeLog @@ -1,3 +1,9 @@ +1999-12-20 Jonathan Blandford + + * gdk-pixbuf/io-gif.c: finished work to make animated gifs load + correctly. Progressive loading needs some work, but that all + needs doing from the gdk-pixbuf-loader end, not here. + 1999-12-17 Jonathan Blandford * gdk-pixbuf/gdk-pixbuf-io.c (gdk_pixbuf_animation_new_from_file): diff --git a/gdk-pixbuf/gdk-pixbuf-io.c b/gdk-pixbuf/gdk-pixbuf-io.c index 429ac0e0dc..7542311d50 100644 --- a/gdk-pixbuf/gdk-pixbuf-io.c +++ b/gdk-pixbuf/gdk-pixbuf-io.c @@ -396,7 +396,7 @@ gdk_pixbuf_animation_new_from_file (const gchar *filename) frame->x_offset = 0; frame->y_offset = 0; - frame->delaytime = -1; + frame->delay_time = -1; frame->action = GDK_PIXBUF_FRAME_RETAIN; fseek (f, 0, SEEK_SET); diff --git a/gdk-pixbuf/gdk-pixbuf.h b/gdk-pixbuf/gdk-pixbuf.h index 75823e2906..ff93c25d00 100644 --- a/gdk-pixbuf/gdk-pixbuf.h +++ b/gdk-pixbuf/gdk-pixbuf.h @@ -63,7 +63,7 @@ struct _GdkPixbufFrame gushort x_offset; gushort y_offset; - gint delaytime; + gint delay_time; GdkPixbufFrameAction action; }; diff --git a/gdk-pixbuf/io-gif.c b/gdk-pixbuf/io-gif.c index e5cef27db3..1a0fc963cb 100644 --- a/gdk-pixbuf/io-gif.c +++ b/gdk-pixbuf/io-gif.c @@ -31,11 +31,8 @@ * read_gif, and lets you call it again assuming that the bytes are there. * * A note on Animations: - * It actually wouldn't be that hard to add support for Gif Animations. You'd - * need, of course, to get the necessary info from the extension, and read the - * private colormap into it's own frame, instead of context->color_map. You'd - * also need to stop it from moving to GIF_DONE at the end of gif_get_lzw, (and - * of course generate the necessary frames. + * Currently, it doesn't correctly read the different colormap per frame. This + * needs implementing sometime. * * Return vals. * Unless otherwise specified, these are the return vals for most functions: @@ -116,6 +113,8 @@ struct _GifContext unsigned int background; unsigned int aspect_ratio; GdkPixbuf *pixbuf; + GdkPixbufAnimation *animation; + GdkPixbufFrame *frame; Gif89 gif89; /* stuff per frame. As we only support the first one, not so @@ -343,6 +342,10 @@ gif_get_extension (GifContext *context) if (context->pixbuf == NULL) { /* I only want to set the transparency if I haven't * created the pixbuf yet. */ + context->gif89.disposal = (context->block_buf[0] >> 2) & 0x7; + context->gif89.input_flag = (context->block_buf[0] >> 1) & 0x1; + context->gif89.delay_time = LM_to_uint (context->block_buf[1], context->block_buf[2]); + if ((context->block_buf[0] & 0x1) != 0) { context->gif89.transparent = context->block_buf[3]; } else { @@ -658,6 +661,7 @@ gif_get_lzw (GifContext *context) gint v; if (context->pixbuf == NULL) { + g_print ("making a new pixbuf\n"); context->pixbuf = gdk_pixbuf_new (ART_PIX_RGB, context->gif89.transparent, 8, @@ -666,8 +670,31 @@ gif_get_lzw (GifContext *context) if (context->prepare_func) (* context->prepare_func) (context->pixbuf, context->user_data); + if (context->animation) { + context->frame = g_new (GdkPixbufFrame, 1); + context->frame->x_offset = 0; + context->frame->y_offset = 0; + context->frame->delay_time = context->gif89.delay_time; + switch (context->gif89.disposal) { + case 0: + case 1: + context->frame->action = GDK_PIXBUF_FRAME_RETAIN; + break; + case 2: + context->frame->action = GDK_PIXBUF_FRAME_DISPOSE; + break; + case 3: + context->frame->action = GDK_PIXBUF_FRAME_REVERT; + break; + default: + context->frame->action = GDK_PIXBUF_FRAME_RETAIN; + break; + } + context->frame->pixbuf = context->pixbuf; + context->animation->n_frames ++; + context->animation->frames = g_list_append (context->animation->frames, context->frame); + } } - dest = gdk_pixbuf_get_pixels (context->pixbuf); bound_flag = FALSE; @@ -749,7 +776,10 @@ gif_get_lzw (GifContext *context) } done: /* we got enough data. there may be more (ie, newer layers) but we can quit now */ - context->state = GIF_DONE; + if (context->animation) { + context->state = GIF_GET_NEXT_STEP; + } else + context->state = GIF_DONE; v = 0; finished_data: if (bound_flag && context->update_func) { @@ -785,6 +815,11 @@ gif_get_lzw (GifContext *context) } } + if (context->animation && context->state == GIF_GET_NEXT_STEP) { + context->pixbuf = NULL; + context->frame = NULL; + } + return v; } @@ -865,7 +900,6 @@ gif_init (GifContext *context) context->color_resolution = (((buf[4] & 0x70) >> 3) + 1); context->background = buf[5]; context->aspect_ratio = buf[6]; - context->pixbuf = NULL; if (BitSet (buf[4], LOCALCOLORMAP)) { gif_set_get_colormap (context); @@ -891,7 +925,12 @@ gif_get_frame_info (GifContext *context) /* Okay, we got all the info we need. Lets record it */ context->frame_len = LM_to_uint (buf[4], buf[5]); context->frame_height = LM_to_uint (buf[6], buf[7]); + if (context->frame) { + context->frame->x_offset = LM_to_uint (buf[0], buf[1]); + context->frame->y_offset = LM_to_uint (buf[2], buf[3]); + } if (context->frame_height > context->height) { + /* we don't want to resize things. So we exit */ context->state = GIF_DONE; return -2; } @@ -1131,3 +1170,21 @@ image_load_increment (gpointer data, guchar *buf, guint size) } return TRUE; } + +GdkPixbufAnimation * +image_load_animation (FILE *file) +{ + GifContext *context; + + g_return_val_if_fail (file != NULL, NULL); + + context = new_context (); + context->animation = g_new (GdkPixbufAnimation, 1); + context->animation->n_frames = 0; + context->animation->frames = NULL; + context->file = file; + + gif_main_loop (context); + + return context->animation; +}