Merge pull request #1385 from DarthSim/feature/optimize_gif
Add GIF optimization options to …
This commit is contained in:
commit
43d678c145
@ -692,7 +692,7 @@ if test x"$magick6" = x"yes"; then
|
|||||||
# IM
|
# IM
|
||||||
save_LIBS="$LIBS"
|
save_LIBS="$LIBS"
|
||||||
LIBS="$LIBS $MAGICK_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"
|
LIBS="$save_LIBS"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
@ -205,6 +205,31 @@ magick_set_number_scenes( ImageInfo *image_info, int scene, int number_scenes )
|
|||||||
image_info->scenes = strdup( page );
|
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?
|
/* Does a few bytes look like a file IM can handle?
|
||||||
*/
|
*/
|
||||||
gboolean
|
gboolean
|
||||||
@ -445,6 +470,43 @@ magick_set_number_scenes( ImageInfo *image_info, int scene, int number_scenes )
|
|||||||
#endif
|
#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?
|
/* Does a few bytes look like a file IM can handle?
|
||||||
*/
|
*/
|
||||||
gboolean
|
gboolean
|
||||||
|
@ -84,6 +84,10 @@ int magick_set_vips_profile( VipsImage *im, Image *image );
|
|||||||
int magick_set_magick_profile( Image *image,
|
int magick_set_magick_profile( Image *image,
|
||||||
VipsImage *im, ExceptionInfo *exception );
|
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 );
|
gboolean magick_ismagick( const unsigned char *bytes, size_t length );
|
||||||
|
|
||||||
#endif /*HAVE_MAGICK6*/
|
#endif /*HAVE_MAGICK6*/
|
||||||
|
@ -10,6 +10,8 @@
|
|||||||
* - support "strip" option
|
* - support "strip" option
|
||||||
* 6/7/19 [deftomat]
|
* 6/7/19 [deftomat]
|
||||||
* - support array of delays
|
* - 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 *filename; /* NULL during buffer output */
|
||||||
char *format;
|
char *format;
|
||||||
int quality;
|
int quality;
|
||||||
|
gboolean optimize_gif_frames;
|
||||||
|
gboolean optimize_gif_transparency;
|
||||||
|
|
||||||
ImageInfo *image_info;
|
ImageInfo *image_info;
|
||||||
ExceptionInfo *exception;
|
ExceptionInfo *exception;
|
||||||
@ -365,6 +369,24 @@ vips_foreign_save_magick_build( VipsObject *object )
|
|||||||
vips_foreign_save_magick_write_block, magick ) )
|
vips_foreign_save_magick_write_block, magick ) )
|
||||||
return( -1 );
|
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 );
|
return( 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -428,6 +450,20 @@ vips_foreign_save_magick_class_init( VipsForeignSaveMagickClass *class )
|
|||||||
VIPS_ARGUMENT_OPTIONAL_INPUT,
|
VIPS_ARGUMENT_OPTIONAL_INPUT,
|
||||||
G_STRUCT_OFFSET( VipsForeignSaveMagick, quality ),
|
G_STRUCT_OFFSET( VipsForeignSaveMagick, quality ),
|
||||||
0, 100, 0 );
|
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
|
static void
|
||||||
@ -586,6 +622,8 @@ vips_foreign_save_magick_buffer_init( VipsForeignSaveMagickBuffer *buffer )
|
|||||||
*
|
*
|
||||||
* * @quality: %gint, quality factor
|
* * @quality: %gint, quality factor
|
||||||
* * @format: %gchararray, format to save as
|
* * @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.
|
* 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
|
* Use @format to explicitly set the save format, for example, "BMP". Otherwise
|
||||||
* the format is guessed from the filename suffix.
|
* 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().
|
* See also: vips_magicksave_buffer(), vips_magickload().
|
||||||
*
|
*
|
||||||
* Returns: 0 on success, -1 on error.
|
* Returns: 0 on success, -1 on error.
|
||||||
@ -622,6 +669,8 @@ vips_magicksave( VipsImage *in, const char *filename, ... )
|
|||||||
*
|
*
|
||||||
* * @quality: %gint, quality factor
|
* * @quality: %gint, quality factor
|
||||||
* * @format: %gchararray, format to save as
|
* * @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.
|
* As vips_magicksave(), but save to a memory buffer.
|
||||||
*
|
*
|
||||||
|
Loading…
Reference in New Issue
Block a user