Skip to content
Permalink
Browse files

Add `optimize_gif_frames` and `optimize_gif_transparency` options to …

…`vips_magicksave`
  • Loading branch information...
DarthSim committed Aug 5, 2019
1 parent def0e73 commit c7e0c073ca544e855cb219871ecb9df9f24f1706
Showing with 116 additions and 1 deletion.
  1. +1 −1 configure.ac
  2. +62 −0 libvips/foreign/magick.c
  3. +4 −0 libvips/foreign/magick.h
  4. +49 −0 libvips/foreign/magicksave.c
@@ -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

@@ -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
@@ -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*/
@@ -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.
*

0 comments on commit c7e0c07

Please sign in to comment.
You can’t perform that action at this time.