From 6d23a3615e34bb710f80f48482ebb350bd4a3a53 Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Thu, 9 Dec 2021 13:00:58 +0000 Subject: [PATCH] add a fallback path for gif save if no cgif Via imagemagick. See https://github.com/libvips/libvips/issues/2574 --- ChangeLog | 1 + configure.ac | 2 +- libvips/foreign/cgifsave.c | 2 +- libvips/foreign/foreign.c | 9 ++- libvips/foreign/vips2magick.c | 133 ++++++++++++++++++++++++++-------- 5 files changed, 111 insertions(+), 36 deletions(-) diff --git a/ChangeLog b/ChangeLog index f85a91cf..e3384b24 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,7 @@ 26/11/21 started 8.12.2 - make exif resuint optional and default to inch - win: don't set create time on inappropriate file descriptors [lovell] +- fall back to magicksave for gif if cgif is not present [erik-frontify] 21/11/21 started 8.12.1 - fix insert [chregu] diff --git a/configure.ac b/configure.ac index 3ae21afb..7d5746ab 100644 --- a/configure.ac +++ b/configure.ac @@ -1501,6 +1501,7 @@ RAD load/save: $with_radiance, \ Analyze7 load/save: $with_analyze, \ PPM load/save: $with_ppm, \ GIF load: $with_nsgif, \ +GIF save with cgif: $with_cgif, \ EXIF metadata support with libexif: $with_libexif, \ JPEG load/save with libjpeg: $with_jpeg, \ JXL load/save with libjxl: $with_libjxl (dynamic module: $with_libjxl_module), \ @@ -1520,7 +1521,6 @@ OpenSlide load: $with_openslide (dynamic module: $with_openslide_module), \ Matlab load with matio: $with_matio, \ NIfTI load/save with niftiio: $with_nifti, \ FITS load/save with cfitsio: $with_cfitsio, \ -GIF save with cgif: $with_cgif, \ Magick package: $with_magickpackage (dynamic module: $with_magick_module), \ Magick API version: $magick_version, \ load with libMagickCore: $enable_magickload, \ diff --git a/libvips/foreign/cgifsave.c b/libvips/foreign/cgifsave.c index 048d7d47..debe5688 100644 --- a/libvips/foreign/cgifsave.c +++ b/libvips/foreign/cgifsave.c @@ -31,8 +31,8 @@ */ /* -#define DEBUG_VERBOSE #define DEBUG_PERCENT +#define DEBUG_VERBOSE */ #ifdef HAVE_CONFIG_H diff --git a/libvips/foreign/foreign.c b/libvips/foreign/foreign.c index da0515f9..9bf932a6 100644 --- a/libvips/foreign/foreign.c +++ b/libvips/foreign/foreign.c @@ -2866,10 +2866,13 @@ vips_foreign_operation_init( void ) extern GType vips_foreign_load_magick_buffer_get_type( void ); extern GType vips_foreign_load_magick7_file_get_type( void ); extern GType vips_foreign_load_magick7_buffer_get_type( void ); + extern GType vips_foreign_save_magick_file_get_type( void ); - extern GType vips_foreign_save_magick_bmp_file_get_type( void ); extern GType vips_foreign_save_magick_buffer_get_type( void ); + extern GType vips_foreign_save_magick_bmp_file_get_type( void ); extern GType vips_foreign_save_magick_bmp_buffer_get_type( void ); + extern GType vips_foreign_save_magick_gif_file_get_type( void ); + extern GType vips_foreign_save_magick_gif_buffer_get_type( void ); extern GType vips_foreign_save_dz_file_get_type( void ); extern GType vips_foreign_save_dz_buffer_get_type( void ); @@ -3084,9 +3087,11 @@ vips_foreign_operation_init( void ) #if defined(ENABLE_MAGICKSAVE) && !defined(MAGICK_MODULE) vips_foreign_save_magick_file_get_type(); - vips_foreign_save_magick_bmp_file_get_type(); vips_foreign_save_magick_buffer_get_type(); + vips_foreign_save_magick_bmp_file_get_type(); vips_foreign_save_magick_bmp_buffer_get_type(); + vips_foreign_save_magick_gif_file_get_type(); + vips_foreign_save_magick_gif_buffer_get_type(); #endif /*defined(ENABLE_MAGICKSAVE) && !defined(MAGICK_MODULE)*/ #ifdef HAVE_CFITSIO diff --git a/libvips/foreign/vips2magick.c b/libvips/foreign/vips2magick.c index c2b3c305..764ce819 100644 --- a/libvips/foreign/vips2magick.c +++ b/libvips/foreign/vips2magick.c @@ -14,6 +14,8 @@ * - support GIF optimization * 21/4/21 kleisauke * - include GObject part from magicksave.c + * 9/12/21 [erik-frontify] + * - add gif save subclass */ /* @@ -417,6 +419,7 @@ vips_foreign_save_magick_build( VipsObject *object ) */ static const char *vips__save_magick_suffs[] = { NULL }; static const char *vips__save_magick_bmp_suffs[] = { ".bmp", NULL }; +static const char *vips__save_magick_gif_suffs[] = { ".gif", NULL }; /* Save a bit of typing. */ @@ -559,38 +562,6 @@ vips_foreign_save_magick_file_init( VipsForeignSaveMagickFile *file ) { } -typedef VipsForeignSaveMagickFile VipsForeignSaveMagickBmpFile; -typedef VipsForeignSaveMagickFileClass VipsForeignSaveMagickBmpFileClass; - -G_DEFINE_TYPE( VipsForeignSaveMagickBmpFile, vips_foreign_save_magick_bmp_file, - vips_foreign_save_magick_file_get_type() ); - -static void -vips_foreign_save_magick_bmp_file_class_init( - VipsForeignSaveMagickBmpFileClass *class ) -{ - VipsObjectClass *object_class = (VipsObjectClass *) class; - VipsForeignClass *foreign_class = (VipsForeignClass *) class; - VipsOperationClass *operation_class = (VipsOperationClass *) class; - - object_class->nickname = "magicksave_bmp"; - object_class->description = _( "save bmp image with ImageMagick" ); - - foreign_class->suffs = vips__save_magick_bmp_suffs; - - /* Hide from UI. - */ - operation_class->flags = VIPS_OPERATION_DEPRECATED; -} - -static void -vips_foreign_save_magick_bmp_file_init( VipsForeignSaveMagickBmpFile *file ) -{ - VipsForeignSaveMagick *magick = (VipsForeignSaveMagick *) file; - - VIPS_SETSTR( magick->format, "bmp" ); -} - typedef struct _VipsForeignSaveMagickBuffer { VipsForeignSaveMagick parent_object; @@ -664,6 +635,38 @@ vips_foreign_save_magick_buffer_init( VipsForeignSaveMagickBuffer *buffer ) { } +typedef VipsForeignSaveMagickFile VipsForeignSaveMagickBmpFile; +typedef VipsForeignSaveMagickFileClass VipsForeignSaveMagickBmpFileClass; + +G_DEFINE_TYPE( VipsForeignSaveMagickBmpFile, vips_foreign_save_magick_bmp_file, + vips_foreign_save_magick_file_get_type() ); + +static void +vips_foreign_save_magick_bmp_file_class_init( + VipsForeignSaveMagickBmpFileClass *class ) +{ + VipsObjectClass *object_class = (VipsObjectClass *) class; + VipsForeignClass *foreign_class = (VipsForeignClass *) class; + VipsOperationClass *operation_class = (VipsOperationClass *) class; + + object_class->nickname = "magicksave_bmp"; + object_class->description = _( "save bmp image with ImageMagick" ); + + foreign_class->suffs = vips__save_magick_bmp_suffs; + + /* Hide from UI. + */ + operation_class->flags = VIPS_OPERATION_DEPRECATED; +} + +static void +vips_foreign_save_magick_bmp_file_init( VipsForeignSaveMagickBmpFile *file ) +{ + VipsForeignSaveMagick *magick = (VipsForeignSaveMagick *) file; + + VIPS_SETSTR( magick->format, "bmp" ); +} + typedef VipsForeignSaveMagickBuffer VipsForeignSaveMagickBmpBuffer; typedef VipsForeignSaveMagickBufferClass VipsForeignSaveMagickBmpBufferClass; @@ -698,4 +701,70 @@ vips_foreign_save_magick_bmp_buffer_init( VIPS_SETSTR( magick->format, "bmp" ); } +typedef VipsForeignSaveMagickFile VipsForeignSaveMagickGifFile; +typedef VipsForeignSaveMagickFileClass VipsForeignSaveMagickGifFileClass; + +G_DEFINE_TYPE( VipsForeignSaveMagickGifFile, vips_foreign_save_magick_gif_file, + vips_foreign_save_magick_file_get_type() ); + +static void +vips_foreign_save_magick_gif_file_class_init( + VipsForeignSaveMagickGifFileClass *class ) +{ + VipsObjectClass *object_class = (VipsObjectClass *) class; + VipsForeignClass *foreign_class = (VipsForeignClass *) class; + VipsOperationClass *operation_class = (VipsOperationClass *) class; + + object_class->nickname = "magicksave_gif"; + object_class->description = _( "save gif image with ImageMagick" ); + + foreign_class->suffs = vips__save_magick_gif_suffs; + + /* Hide from UI. + */ + operation_class->flags = VIPS_OPERATION_DEPRECATED; +} + +static void +vips_foreign_save_magick_gif_file_init( VipsForeignSaveMagickGifFile *file ) +{ + VipsForeignSaveMagick *magick = (VipsForeignSaveMagick *) file; + + VIPS_SETSTR( magick->format, "gif" ); +} + +typedef VipsForeignSaveMagickBuffer VipsForeignSaveMagickGifBuffer; +typedef VipsForeignSaveMagickBufferClass VipsForeignSaveMagickGifBufferClass; + +G_DEFINE_TYPE( VipsForeignSaveMagickGifBuffer, + vips_foreign_save_magick_gif_buffer, + vips_foreign_save_magick_buffer_get_type() ); + +static void +vips_foreign_save_magick_gif_buffer_class_init( + VipsForeignSaveMagickGifBufferClass *class ) +{ + VipsObjectClass *object_class = (VipsObjectClass *) class; + VipsForeignClass *foreign_class = (VipsForeignClass *) class; + VipsOperationClass *operation_class = (VipsOperationClass *) class; + + object_class->nickname = "magicksave_gif_buffer"; + object_class->description = _( "save gif image to magick buffer" ); + + foreign_class->suffs = vips__save_magick_gif_suffs; + + /* Hide from UI. + */ + operation_class->flags = VIPS_OPERATION_DEPRECATED; +} + +static void +vips_foreign_save_magick_gif_buffer_init( + VipsForeignSaveMagickGifBuffer *buffer ) +{ + VipsForeignSaveMagick *magick = (VipsForeignSaveMagick *) buffer; + + VIPS_SETSTR( magick->format, "gif" ); +} + #endif /*ENABLE_MAGICKSAVE*/