Merge pull request #1385 from DarthSim/feature/optimize_gif

Add GIF optimization options to …
This commit is contained in:
John Cupitt 2019-08-07 22:32:48 +01:00 committed by GitHub
commit 43d678c145
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 116 additions and 1 deletions

View File

@ -692,7 +692,7 @@ if test x"$magick6" = x"yes"; then
# IM
save_LIBS="$LIBS"
LIBS="$LIBS $MAGICK_LIBS"
AC_CHECK_FUNCS([InheritException AcquireExceptionInfo SetImageProperty SetImageExtent AcquireImage GetVirtualPixels ResetImageProfileIterator ResetImageAttributeIterator ResetImagePropertyIterator MagickCoreGenesis SetImageOption BlobToStringInfo])
AC_CHECK_FUNCS([InheritException AcquireExceptionInfo SetImageProperty SetImageExtent AcquireImage GetVirtualPixels ResetImageProfileIterator ResetImageAttributeIterator ResetImagePropertyIterator MagickCoreGenesis SetImageOption BlobToStringInfo OptimizePlusImageLayers OptimizeImageTransparency])
LIBS="$save_LIBS"
fi

View File

@ -205,6 +205,31 @@ magick_set_number_scenes( ImageInfo *image_info, int scene, int number_scenes )
image_info->scenes = strdup( page );
}
int
magick_optimize_image_layers( Image **images, ExceptionInfo *exception )
{
Image *tmp;
tmp = OptimizePlusImageLayers(*images, exception );
if ( exception->severity != UndefinedException )
return MagickFalse;
VIPS_FREEF( DestroyImageList, *images );
*images = tmp;
return MagickTrue;
}
int
magick_optimize_image_transparency( const Image *images,
ExceptionInfo *exception )
{
OptimizeImageTransparency(images, exception);
return ( exception->severity == UndefinedException );
}
/* Does a few bytes look like a file IM can handle?
*/
gboolean
@ -445,6 +470,43 @@ magick_set_number_scenes( ImageInfo *image_info, int scene, int number_scenes )
#endif
}
int
magick_optimize_image_layers( Image **images, ExceptionInfo *exception )
{
#ifdef HAS_OPTIMIZEPLUSIMAGELAYERS
Image *tmp;
tmp = OptimizePlusImageLayers(*images, exception );
if ( exception->severity != UndefinedException )
return MagickFalse;
VIPS_FREEF( DestroyImageList, *images );
*images = tmp;
return MagickTrue;
#else
g_warning( "%s", _( "layers optimization is not supported by your version "
"of libMagick" ) );
return MagickTrue;
#endif
}
int
magick_optimize_image_transparency( const Image *images,
ExceptionInfo *exception )
{
#ifdef HAS_OPTIMIZEIMAGETRANSPARENCY
OptimizeImageTransparency(images, exception);
return ( exception->severity == UndefinedException );
#else
g_warning( "%s", _( "transparency optimization is not supported by your "
"version of libMagick" ) );
return MagickTrue;
#endif
}
/* Does a few bytes look like a file IM can handle?
*/
gboolean

View File

@ -84,6 +84,10 @@ int magick_set_vips_profile( VipsImage *im, Image *image );
int magick_set_magick_profile( Image *image,
VipsImage *im, ExceptionInfo *exception );
int magick_optimize_image_layers( Image **images, ExceptionInfo *exception );
int magick_optimize_image_transparency( const Image *images,
ExceptionInfo *exception );
gboolean magick_ismagick( const unsigned char *bytes, size_t length );
#endif /*HAVE_MAGICK6*/

View File

@ -10,6 +10,8 @@
* - support "strip" option
* 6/7/19 [deftomat]
* - support array of delays
* 5/8/19 DarthSim
* - support GIF optimization
*/
/*
@ -63,6 +65,8 @@ typedef struct _VipsForeignSaveMagick {
char *filename; /* NULL during buffer output */
char *format;
int quality;
gboolean optimize_gif_frames;
gboolean optimize_gif_transparency;
ImageInfo *image_info;
ExceptionInfo *exception;
@ -365,6 +369,24 @@ vips_foreign_save_magick_build( VipsObject *object )
vips_foreign_save_magick_write_block, magick ) )
return( -1 );
if( magick->optimize_gif_frames ) {
if( !magick_optimize_image_layers(&magick->images, magick->exception ) ) {
magick_inherit_exception( magick->exception, magick->images );
magick_vips_error( class->nickname, magick->exception );
return( -1 );
}
}
if( magick->optimize_gif_transparency ) {
if( !magick_optimize_image_transparency(magick->images, magick->exception) ) {
magick_inherit_exception( magick->exception, magick->images );
magick_vips_error( class->nickname, magick->exception );
return( -1 );
}
}
return( 0 );
}
@ -428,6 +450,20 @@ vips_foreign_save_magick_class_init( VipsForeignSaveMagickClass *class )
VIPS_ARGUMENT_OPTIONAL_INPUT,
G_STRUCT_OFFSET( VipsForeignSaveMagick, quality ),
0, 100, 0 );
VIPS_ARG_BOOL( class, "optimize_gif_frames", 4,
_( "Optimize_gif_frames" ),
_( "Apply GIF frames optimization" ),
VIPS_ARGUMENT_OPTIONAL_INPUT,
G_STRUCT_OFFSET( VipsForeignSaveMagick, optimize_gif_frames ),
FALSE );
VIPS_ARG_BOOL( class, "optimize_gif_transparency", 5,
_( "Optimize_gif_transparency" ),
_( "Apply GIF transparency optimization" ),
VIPS_ARGUMENT_OPTIONAL_INPUT,
G_STRUCT_OFFSET( VipsForeignSaveMagick, optimize_gif_transparency ),
FALSE );
}
static void
@ -586,6 +622,8 @@ vips_foreign_save_magick_buffer_init( VipsForeignSaveMagickBuffer *buffer )
*
* * @quality: %gint, quality factor
* * @format: %gchararray, format to save as
* * @optimize_gif_frames: %gboolean, apply GIF frames optimization
* * @optimize_gif_transparency: %gboolean, apply GIF transparency optimization
*
* Write an image using libMagick.
*
@ -594,6 +632,15 @@ vips_foreign_save_magick_buffer_init( VipsForeignSaveMagickBuffer *buffer )
* Use @format to explicitly set the save format, for example, "BMP". Otherwise
* the format is guessed from the filename suffix.
*
* If @optimize_gif_frames is set, GIF frames are cropped to the smallest size
* while preserving the results of the GIF animation. This takes some time for
* computation but saves some time on encoding and produces smaller files in
* some cases.
*
* If @optimize_gif_transparency is set, pixels that don't change the image
* through animation are made transparent. This takes some time for computation
* but saves some time on encoding and produces smaller files in some cases.
*
* See also: vips_magicksave_buffer(), vips_magickload().
*
* Returns: 0 on success, -1 on error.
@ -622,6 +669,8 @@ vips_magicksave( VipsImage *in, const char *filename, ... )
*
* * @quality: %gint, quality factor
* * @format: %gchararray, format to save as
* * @optimize_gif_frames: %gboolean, apply GIF frames optimization
* * @optimize_gif_transparency: %gboolean, apply GIF transparency optimization
*
* As vips_magicksave(), but save to a memory buffer.
*