From 777c360774832ac0a258af7b881e6a3842e9970e Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Sat, 6 Jul 2019 11:34:20 +0100 Subject: [PATCH] safer gifload delay array init - remove assumptions about n_pages - minor reformatting --- ChangeLog | 1 + libvips/foreign/gifload.c | 32 ++++++++++++++++++++++++++------ libvips/foreign/vips2webp.c | 7 +++++-- 3 files changed, 32 insertions(+), 8 deletions(-) diff --git a/ChangeLog b/ChangeLog index ad086f4e..27fb7bca 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,7 @@ 20/6/19 started 8.9.0 - add vips_image_get/set_array_int() - disable webp alpha output if all frame fill the canvas and are solid +- support arrays of delays for animated images [deftomat] 24/5/19 started 8.8.1 - improve realpath() use on older libc diff --git a/libvips/foreign/gifload.c b/libvips/foreign/gifload.c index 690f4a68..b72ec1f5 100644 --- a/libvips/foreign/gifload.c +++ b/libvips/foreign/gifload.c @@ -22,6 +22,8 @@ * - init pages to 0 before load * 14/2/19 * - rework as a sequential loader ... simpler, much lower mem use + * 6/7/19 + * - support array of delays */ /* @@ -135,6 +137,7 @@ typedef struct _VipsForeignLoadGif { /* Delays between frames (in milliseconds). */ int *delays; + int delays_length; /* Number of times to loop the animation. */ @@ -519,10 +522,22 @@ vips_foreign_load_gif_scan_extension( VipsForeignLoadGif *gif ) gif->has_transparency = TRUE; } - if( gif->n_pages % 64 == 0 ) - gif->delays = (int *) g_realloc( gif->delays, (gif->n_pages + 64) * sizeof(int) ); + if( gif->n_pages >= gif->delays_length ) { + int old = gif->delays_length; + int i; - gif->delays[gif->n_pages] = (extension[2] | (extension[3] << 8)) * 10; + gif->delays_length = + gif->delays_length + gif->n_pages + 64; + gif->delays = (int *) g_realloc( gif->delays, + gif->delays_length * sizeof( int ) ); + for( i = old; i < gif->delays_length; i++ ) + gif->delays[i] = 40; + } + + /* giflib uses centiseconds, we use ms. + */ + gif->delays[gif->n_pages] = + (extension[2] | (extension[3] << 8)) * 10; while( extension != NULL ) if( vips_foreign_load_gif_ext_next( gif, @@ -575,10 +590,14 @@ vips_foreign_load_gif_set_header( VipsForeignLoadGif *gif, VipsImage *image ) vips_image_set_int( image, "gif-loop", gif->loop ); if( gif->delays ) { + /* The deprecated gif-delay field is in centiseconds. + */ vips_image_set_int( image, - "gif-delay", VIPS_RINT( gif->delays[0] / 10.0 ) ); - vips_image_set_array_int( image, "delay", gif->delays, gif->n_pages ); - } else + "gif-delay", VIPS_RINT( gif->delays[0] / 10.0 ) ); + vips_image_set_array_int( image, + "delay", gif->delays, gif->n_pages ); + } + else vips_image_set_int( image, "gif-delay", 4 ); if( gif->comment ) @@ -1122,6 +1141,7 @@ vips_foreign_load_gif_init( VipsForeignLoadGif *gif ) gif->n = 1; gif->transparency = -1; gif->delays = NULL; + gif->delays_length = 0; gif->loop = 0; gif->comment = NULL; gif->dispose = 0; diff --git a/libvips/foreign/vips2webp.c b/libvips/foreign/vips2webp.c index b3e3ecc7..3e207457 100644 --- a/libvips/foreign/vips2webp.c +++ b/libvips/foreign/vips2webp.c @@ -306,10 +306,13 @@ get_array_int( VipsImage *image, const char *field, int* n ) /* Returns a delay on a given index or the default delay. */ static int -extract_delay( int index, int *delays, int delays_length, int default_delay ) +extract_delay( int index, const int *delays, int delays_length, + int default_delay ) { - if( delays == NULL || index > delays_length ) + if( delays == NULL || + index > delays_length ) return( default_delay ); + return( delays[index] ); }