keep magicksave delay array alive for longer

fixes a segv in magicksave_buffer ... we could try to use delay after im
had been unreffed in some circumstances
This commit is contained in:
John Cupitt 2019-07-06 17:45:41 +01:00
parent 3871369d3e
commit c8ca8f02ba
2 changed files with 23 additions and 5 deletions

View File

@ -72,6 +72,7 @@ typedef struct _VipsForeignSaveMagick {
Image *current_image;
int page_height;
GValue delay_gvalue;
int *delays;
int delays_length;
@ -99,6 +100,7 @@ vips_foreign_save_magick_dispose( GObject *gobject )
VIPS_FREEF( DestroyImageList, magick->images );
VIPS_FREEF( DestroyImageInfo, magick->image_info );
VIPS_FREEF( magick_destroy_exception, magick->exception );
g_value_unset( &magick->delay_gvalue );
G_OBJECT_CLASS( vips_foreign_save_magick_parent_class )->
dispose( gobject );
@ -349,10 +351,15 @@ vips_foreign_save_magick_build( VipsObject *object )
magick->page_height = vips_image_get_page_height( im );
if( vips_image_get_typeof( im, "delay" ) &&
vips_image_get_array_int( im,
"delay", &magick->delays, &magick->delays_length ) )
return( -1 );
/* Get as a gvalue so we can keep a ref to the delay array while we
* need it.
*/
if( vips_image_get_typeof( im, "delay" ) ) {
if( vips_image_get( im, "delay", &magick->delay_gvalue ) )
return( -1 );
magick->delays = vips_value_get_array_int(
&magick->delay_gvalue, &magick->delays_length );
}
if( vips_sink_disc( im,
vips_foreign_save_magick_write_block, magick ) )

View File

@ -459,6 +459,15 @@ class TestForeign:
self.save_load_buffer("magicksave_buffer", "magickload_buffer",
self.colour, 40, format="JPG")
# try an animation
if have("gifload"):
x1 = pyvips.Image.new_from_file(GIF_ANIM_FILE, n=-1)
w1 = x1.magicksave_buffer(format="GIF")
x2 = pyvips.Image.new_from_buffer(w1, "", n=-1)
assert x1.get("delay") == x2.get("delay")
assert x1.get("page-height") == x2.get("page-height")
assert x1.get("gif-loop") == x2.get("gif-loop")
@skip_if_no("webpload")
def test_webp(self):
def webp_valid(im):
@ -517,7 +526,7 @@ class TestForeign:
x2 = pyvips.Image.new_from_buffer(w1, "", n=-1)
assert x1.width == x2.width
assert x1.height == x2.height
assert x1.get("gif-delay") == x2.get("gif-delay")
assert x1.get("delay") == x2.get("delay")
assert x1.get("page-height") == x2.get("page-height")
assert x1.get("gif-loop") == x2.get("gif-loop")
@ -636,6 +645,8 @@ class TestForeign:
x2 = pyvips.Image.new_from_file(GIF_ANIM_FILE, n=-1)
assert x2.height == 5 * x1.height
# our test gif has delay 0 for the first frame set in error
assert x2.get("delay") == [0, 50, 50, 50, 50]
x2 = pyvips.Image.new_from_file(GIF_ANIM_FILE, page=1, n=-1)
assert x2.height == 4 * x1.height