From 3ad3c30ab4f3791e438558e4a9cf5481da2f1156 Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Mon, 10 Feb 2020 17:34:45 +0000 Subject: [PATCH 1/2] better handling of GIFs with out of bounds frames The recent reworking of gifload did not check for out of bounds frames before setting DISPOSE_BACKGROUND. --- libvips/foreign/gifload.c | 47 ++++++++++++++++++++++----------------- 1 file changed, 26 insertions(+), 21 deletions(-) diff --git a/libvips/foreign/gifload.c b/libvips/foreign/gifload.c index 5a13c3bf..370d48b6 100644 --- a/libvips/foreign/gifload.c +++ b/libvips/foreign/gifload.c @@ -846,14 +846,14 @@ vips_foreign_load_gif_build_cmap( VipsForeignLoadGif *gif ) static void vips_foreign_load_gif_render_line( VipsForeignLoadGif *gif, - int width, VipsPel * restrict dst ) + int width, VipsPel * restrict dst, VipsPel * restrict src ) { - guint32 *idst = (guint32 *) dst; + guint32 * restrict idst = (guint32 *) dst; int x; for( x = 0; x < width; x++ ) { - VipsPel v = gif->line[x]; + VipsPel v = src[x]; if( v != gif->transparent_index ) idst[x] = gif->cmap[v]; @@ -873,19 +873,6 @@ vips_foreign_load_gif_render( VipsForeignLoadGif *gif ) return( -1 ); } - /* Update the colour map for this frame. - */ - vips_foreign_load_gif_build_cmap( gif ); - - /* PREVIOUS means we init the frame with the last un-disposed frame. - * So the last un-disposed frame is used as a backdrop for the new - * frame. - */ - if( gif->dispose == DISPOSE_PREVIOUS ) - memcpy( VIPS_IMAGE_ADDR( gif->scratch, 0, 0 ), - VIPS_IMAGE_ADDR( gif->previous, 0, 0 ), - VIPS_IMAGE_SIZEOF_IMAGE( gif->scratch ) ); - /* giflib does not check that the Left / Top / Width / Height for this * Image is inside the canvas. * @@ -906,8 +893,26 @@ vips_foreign_load_gif_render( VipsForeignLoadGif *gif ) "out of bounds frame of %d x %d pixels at %d x %d\n", file->Image.Width, file->Image.Height, file->Image.Left, file->Image.Top ); + + /* Don't flag an error -- many GIFs have this problem. + */ + return( 0 ); } - else if( file->Image.Interlace ) { + + /* Update the colour map for this frame. + */ + vips_foreign_load_gif_build_cmap( gif ); + + /* PREVIOUS means we init the frame with the last un-disposed frame. + * So the last un-disposed frame is used as a backdrop for the new + * frame. + */ + if( gif->dispose == DISPOSE_PREVIOUS ) + memcpy( VIPS_IMAGE_ADDR( gif->scratch, 0, 0 ), + VIPS_IMAGE_ADDR( gif->previous, 0, 0 ), + VIPS_IMAGE_SIZEOF_IMAGE( gif->scratch ) ); + + if( file->Image.Interlace ) { int i; VIPS_DEBUG_MSG( "vips_foreign_load_gif_render: " @@ -931,7 +936,7 @@ vips_foreign_load_gif_render( VipsForeignLoadGif *gif ) } vips_foreign_load_gif_render_line( gif, - file->Image.Width, dst ); + file->Image.Width, dst, gif->line ); } } } @@ -954,14 +959,14 @@ vips_foreign_load_gif_render( VipsForeignLoadGif *gif ) } vips_foreign_load_gif_render_line( gif, - file->Image.Width, dst ); + file->Image.Width, dst, gif->line ); } } /* Copy the result to frame, which then is picked up from outside */ memcpy( VIPS_IMAGE_ADDR( gif->frame, 0, 0 ), - VIPS_IMAGE_ADDR(gif->scratch, 0, 0 ), + VIPS_IMAGE_ADDR( gif->scratch, 0, 0 ), VIPS_IMAGE_SIZEOF_IMAGE( gif->frame ) ); if( gif->dispose == DISPOSE_BACKGROUND ) { @@ -996,7 +1001,7 @@ vips_foreign_load_gif_render( VipsForeignLoadGif *gif ) * DISPOSE_PREVIOUS is specified in a later frame. */ memcpy( VIPS_IMAGE_ADDR( gif->previous, 0, 0 ), - VIPS_IMAGE_ADDR(gif->frame, 0, 0 ), + VIPS_IMAGE_ADDR( gif->frame, 0, 0 ), VIPS_IMAGE_SIZEOF_IMAGE( gif->previous ) ); /* Reset values, as Graphic Control Extension is optional From 54ff9dabf7e20e01d4ee07183b24ab6861909192 Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Tue, 11 Feb 2020 15:20:12 +0000 Subject: [PATCH 2/2] trim README a little --- README.md | 55 ++----------------------------------------------------- 1 file changed, 2 insertions(+), 53 deletions(-) diff --git a/README.md b/README.md index a9373538..1b8e6e52 100644 --- a/README.md +++ b/README.md @@ -89,7 +89,6 @@ Run the test suite with: Run a specific test with: - pytest --verbose pytest test/test-suite/test_foreign.py -k test_tiff # Building libvips from git @@ -103,7 +102,7 @@ and `gobject-introspection`, see the dependencies section below. For example: brew install gtk-doc -Then build the build system with: +Then generate the build system with: ./autogen.sh --prefix=/home/john/vips @@ -114,56 +113,6 @@ Debug build: make make install -Leak check. Use the suppressions file `supp/valgrind.supp`. - - export G_DEBUG=gc-friendly - valgrind --suppressions=vips-x.y.z/supp/valgrind.supp \ - --leak-check=yes \ - vips ... > vips-vg.log 2>&1 - -Memory error debug: - - valgrind --vgdb=yes --vgdb-error=0 vips ... - -valgrind threading check: - - valgrind --tool=helgrind vips ... > vips-vg.log 2>&1 - -Clang build: - - CC=clang CXX=clang++ ./configure --prefix=/home/john/vips - -Clang static analysis: - - scan-build ./configure --disable-introspection --disable-debug - scan-build -o scan -v make - scan-view scan/2013-11-22-2 - -Clang dynamic analysis: - - FLAGS="-g -O1 -fno-omit-frame-pointer" - CC=clang CXX=clang++ LD=clang \ - CFLAGS="$FLAGS" CXXFLAGS="$FLAGS" LDFLAGS=-fsanitize=address \ - ./configure --prefix=/home/john/vips - - FLAGS="-O1 -g -fsanitize=thread" - FLAGS="$FLAGS -fPIC" - FLAGS="$FLAGS -fno-omit-frame-pointer -fno-optimize-sibling-calls" - CC=clang CXX=clang++ LD=clang \ - CFLAGS="$FLAGS" CXXFLAGS="$FLAGS" \ - LDFLAGS="-fsanitize=thread -fPIC" \ - ./configure --prefix=/home/john/vips \ - --without-magick \ - --disable-introspection - G_DEBUG=gc-friendly vips copy ~/pics/k2.jpg x.jpg >& log - -Build with the GCC auto-vectorizer and diagnostics (or just -O3): - - FLAGS="-O2 -march=native -ffast-math" - FLAGS="$FLAGS -ftree-vectorize -fdump-tree-vect-details" - CFLAGS="$FLAGS" CXXFLAGS="$FLAGS" \ - ./configure --prefix=/home/john/vips - # Dependencies libvips has to have `glib2.0-dev` and `libexpat1-dev`. Other dependencies @@ -284,7 +233,7 @@ If available, vips can load and save WebP images. ### libniftiio -If available, vips can load and save NIFTI images. +If available, vips can load and save NIfTI images. ### OpenEXR