Add lossy compression "preset" option to webpsave
This allows to tune the lossy webp encoder for certain types of images.
This commit is contained in:
parent
7f70abd4ba
commit
f834ea39f6
@ -2458,6 +2458,8 @@ vips_webpload_buffer( void *buf, size_t len, VipsImage **out, ... )
|
||||
* Optional arguments:
|
||||
*
|
||||
* @Q: quality factor
|
||||
* @lossless: enables lossless compression
|
||||
* @preset: #VipsForeignWebpPreset choose lossy compression preset
|
||||
*
|
||||
* See also: vips_webpload(), vips_image_write_to_file().
|
||||
*
|
||||
@ -2486,6 +2488,8 @@ vips_webpsave( VipsImage *in, const char *filename, ... )
|
||||
* Optional arguments:
|
||||
*
|
||||
* @Q: JPEG quality factor
|
||||
* @lossless: enables lossless compression
|
||||
* @preset: #VipsForeignWebpPreset choose lossy compression preset
|
||||
*
|
||||
* See also: vips_webpsave().
|
||||
*
|
||||
|
@ -56,15 +56,41 @@
|
||||
typedef int (*webp_import)( WebPPicture *picture,
|
||||
const uint8_t *rgb, int stride );
|
||||
|
||||
static WebPPreset
|
||||
get_preset( VipsForeignWebpPreset preset )
|
||||
{
|
||||
switch( preset ) {
|
||||
case VIPS_FOREIGN_WEBP_PRESET_DEFAULT:
|
||||
return( WEBP_PRESET_DEFAULT );
|
||||
case VIPS_FOREIGN_WEBP_PRESET_PICTURE:
|
||||
return( WEBP_PRESET_PICTURE );
|
||||
case VIPS_FOREIGN_WEBP_PRESET_PHOTO:
|
||||
return( WEBP_PRESET_PHOTO );
|
||||
case VIPS_FOREIGN_WEBP_PRESET_DRAWING:
|
||||
return( WEBP_PRESET_DRAWING );
|
||||
case VIPS_FOREIGN_WEBP_PRESET_ICON:
|
||||
return( WEBP_PRESET_ICON );
|
||||
case VIPS_FOREIGN_WEBP_PRESET_TEXT:
|
||||
return( WEBP_PRESET_TEXT );
|
||||
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
}
|
||||
|
||||
/* Keep -Wall happy.
|
||||
*/
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
static int
|
||||
write_webp( WebPPicture *pic, VipsImage *in,
|
||||
int Q, gboolean lossless )
|
||||
int Q, gboolean lossless, VipsForeignWebpPreset preset )
|
||||
{
|
||||
VipsImage *memory;
|
||||
WebPConfig config;
|
||||
webp_import import;
|
||||
|
||||
if ( !WebPConfigPreset(&config, WEBP_PRESET_DEFAULT, Q) ) {
|
||||
if ( !WebPConfigPreset(&config, get_preset( preset ), Q) ) {
|
||||
vips_error( "vips2webp",
|
||||
"%s", _( "config version error" ) );
|
||||
return( -1 );
|
||||
@ -112,7 +138,7 @@ write_webp( WebPPicture *pic, VipsImage *in,
|
||||
|
||||
int
|
||||
vips__webp_write_file( VipsImage *in, const char *filename,
|
||||
int Q, gboolean lossless )
|
||||
int Q, gboolean lossless, VipsForeignWebpPreset preset )
|
||||
{
|
||||
WebPPicture pic;
|
||||
WebPMemoryWriter writer;
|
||||
@ -128,7 +154,7 @@ vips__webp_write_file( VipsImage *in, const char *filename,
|
||||
pic.writer = WebPMemoryWrite;
|
||||
pic.custom_ptr = &writer;
|
||||
|
||||
if( write_webp( &pic, in, Q, lossless ) ) {
|
||||
if( write_webp( &pic, in, Q, lossless, preset ) ) {
|
||||
WebPPictureFree( &pic );
|
||||
WebPMemoryWriterClear( &writer );
|
||||
return -1;
|
||||
@ -155,7 +181,7 @@ vips__webp_write_file( VipsImage *in, const char *filename,
|
||||
|
||||
int
|
||||
vips__webp_write_buffer( VipsImage *in, void **obuf, size_t *olen,
|
||||
int Q, gboolean lossless )
|
||||
int Q, gboolean lossless, VipsForeignWebpPreset preset )
|
||||
{
|
||||
WebPPicture pic;
|
||||
WebPMemoryWriter writer;
|
||||
@ -171,7 +197,7 @@ vips__webp_write_buffer( VipsImage *in, void **obuf, size_t *olen,
|
||||
pic.writer = WebPMemoryWrite;
|
||||
pic.custom_ptr = &writer;
|
||||
|
||||
if( write_webp( &pic, in, Q, lossless ) ) {
|
||||
if( write_webp( &pic, in, Q, lossless, preset ) ) {
|
||||
WebPPictureFree( &pic );
|
||||
WebPMemoryWriterClear( &writer );
|
||||
return -1;
|
||||
|
@ -49,9 +49,9 @@ int vips__webp_read_buffer( const void *buf, size_t len,
|
||||
VipsImage *out, int shrink );
|
||||
|
||||
int vips__webp_write_file( VipsImage *out, const char *filename,
|
||||
int Q, gboolean lossless );
|
||||
int Q, gboolean lossless, VipsForeignWebpPreset preset );
|
||||
int vips__webp_write_buffer( VipsImage *out, void **buf, size_t *len,
|
||||
int Q, gboolean lossless );
|
||||
int Q, gboolean lossless, VipsForeignWebpPreset preset );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -60,6 +60,10 @@ typedef struct _VipsForeignSaveWebp {
|
||||
*/
|
||||
gboolean lossless;
|
||||
|
||||
/* Lossy compression preset.
|
||||
*/
|
||||
VipsForeignWebpPreset preset;
|
||||
|
||||
} VipsForeignSaveWebp;
|
||||
|
||||
typedef VipsForeignSaveClass VipsForeignSaveWebpClass;
|
||||
@ -109,6 +113,14 @@ vips_foreign_save_webp_class_init( VipsForeignSaveWebpClass *class )
|
||||
G_STRUCT_OFFSET( VipsForeignSaveWebp, lossless ),
|
||||
FALSE );
|
||||
|
||||
VIPS_ARG_ENUM( class, "preset", 12,
|
||||
_( "preset" ),
|
||||
_( "Preset for lossy compression" ),
|
||||
VIPS_ARGUMENT_OPTIONAL_INPUT,
|
||||
G_STRUCT_OFFSET( VipsForeignSaveWebp, preset ),
|
||||
VIPS_TYPE_FOREIGN_WEBP_PRESET,
|
||||
VIPS_FOREIGN_WEBP_PRESET_DEFAULT );
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
@ -143,7 +155,7 @@ vips_foreign_save_webp_file_build( VipsObject *object )
|
||||
return( -1 );
|
||||
|
||||
if( vips__webp_write_file( save->ready, file->filename,
|
||||
webp->Q, webp->lossless ) )
|
||||
webp->Q, webp->lossless, webp->preset ) )
|
||||
return( -1 );
|
||||
|
||||
return( 0 );
|
||||
@ -205,7 +217,7 @@ vips_foreign_save_webp_buffer_build( VipsObject *object )
|
||||
return( -1 );
|
||||
|
||||
if( vips__webp_write_buffer( save->ready, &obuf, &olen,
|
||||
webp->Q, webp->lossless ) )
|
||||
webp->Q, webp->lossless, webp->preset ) )
|
||||
return( -1 );
|
||||
|
||||
blob = vips_blob_new( (VipsCallbackFn) vips_free, obuf, olen );
|
||||
@ -266,7 +278,7 @@ vips_foreign_save_webp_mime_build( VipsObject *object )
|
||||
return( -1 );
|
||||
|
||||
if( vips__webp_write_buffer( save->ready, &obuf, &olen,
|
||||
webp->Q, webp->lossless ) )
|
||||
webp->Q, webp->lossless, webp->preset ) )
|
||||
return( -1 );
|
||||
|
||||
printf( "Content-length: %zu\r\n", olen );
|
||||
|
@ -14,6 +14,8 @@ GType vips_foreign_flags_get_type (void) G_GNUC_CONST;
|
||||
#define VIPS_TYPE_FOREIGN_FLAGS (vips_foreign_flags_get_type())
|
||||
GType vips_saveable_get_type (void) G_GNUC_CONST;
|
||||
#define VIPS_TYPE_SAVEABLE (vips_saveable_get_type())
|
||||
GType vips_foreign_webp_preset_get_type (void) G_GNUC_CONST;
|
||||
#define VIPS_TYPE_FOREIGN_WEBP_PRESET (vips_foreign_webp_preset_get_type())
|
||||
GType vips_foreign_tiff_compression_get_type (void) G_GNUC_CONST;
|
||||
#define VIPS_TYPE_FOREIGN_TIFF_COMPRESSION (vips_foreign_tiff_compression_get_type())
|
||||
GType vips_foreign_tiff_predictor_get_type (void) G_GNUC_CONST;
|
||||
|
@ -338,6 +338,29 @@ int vips_jpegsave_buffer( VipsImage *in, void **buf, size_t *len, ... )
|
||||
int vips_jpegsave_mime( VipsImage *in, ... )
|
||||
__attribute__((sentinel));
|
||||
|
||||
/**
|
||||
* VipsForeignWebpPreset:
|
||||
* @VIPS_FOREIGN_WEBP_PRESET_DEFAULT: default preset
|
||||
* @VIPS_FOREIGN_WEBP_PRESET_PICTURE: digital picture, like portrait,
|
||||
* inner shot
|
||||
* @VIPS_FOREIGN_WEBP_PRESET_PHOTO: outdoor photograph, with natural lighting
|
||||
* @VIPS_FOREIGN_WEBP_PRESET_DRAWING: hand or line drawing, with high-contrast
|
||||
* details
|
||||
* @VIPS_FOREIGN_WEBP_PRESET_ICON: small-sized colorful images
|
||||
* @VIPS_FOREIGN_WEBP_PRESET_TEXT: text-like
|
||||
*
|
||||
* Tune lossy encoder settings for different image types.
|
||||
*/
|
||||
typedef enum {
|
||||
VIPS_FOREIGN_WEBP_PRESET_DEFAULT,
|
||||
VIPS_FOREIGN_WEBP_PRESET_PICTURE,
|
||||
VIPS_FOREIGN_WEBP_PRESET_PHOTO,
|
||||
VIPS_FOREIGN_WEBP_PRESET_DRAWING,
|
||||
VIPS_FOREIGN_WEBP_PRESET_ICON,
|
||||
VIPS_FOREIGN_WEBP_PRESET_TEXT,
|
||||
VIPS_FOREIGN_WEBP_PRESET_LAST
|
||||
} VipsForeignWebpPreset;
|
||||
|
||||
int vips_webpload( const char *filename, VipsImage **out, ... )
|
||||
__attribute__((sentinel));
|
||||
int vips_webpload_buffer( void *buf, size_t len, VipsImage **out, ... )
|
||||
|
@ -70,6 +70,28 @@ vips_saveable_get_type( void )
|
||||
return( etype );
|
||||
}
|
||||
GType
|
||||
vips_foreign_webp_preset_get_type( void )
|
||||
{
|
||||
static GType etype = 0;
|
||||
|
||||
if( etype == 0 ) {
|
||||
static const GEnumValue values[] = {
|
||||
{VIPS_FOREIGN_WEBP_PRESET_DEFAULT, "VIPS_FOREIGN_WEBP_PRESET_DEFAULT", "default"},
|
||||
{VIPS_FOREIGN_WEBP_PRESET_PICTURE, "VIPS_FOREIGN_WEBP_PRESET_PICTURE", "picture"},
|
||||
{VIPS_FOREIGN_WEBP_PRESET_PHOTO, "VIPS_FOREIGN_WEBP_PRESET_PHOTO", "photo"},
|
||||
{VIPS_FOREIGN_WEBP_PRESET_DRAWING, "VIPS_FOREIGN_WEBP_PRESET_DRAWING", "drawing"},
|
||||
{VIPS_FOREIGN_WEBP_PRESET_ICON, "VIPS_FOREIGN_WEBP_PRESET_ICON", "icon"},
|
||||
{VIPS_FOREIGN_WEBP_PRESET_TEXT, "VIPS_FOREIGN_WEBP_PRESET_TEXT", "text"},
|
||||
{VIPS_FOREIGN_WEBP_PRESET_LAST, "VIPS_FOREIGN_WEBP_PRESET_LAST", "last"},
|
||||
{0, NULL, NULL}
|
||||
};
|
||||
|
||||
etype = g_enum_register_static( "VipsForeignWebpPreset", values );
|
||||
}
|
||||
|
||||
return( etype );
|
||||
}
|
||||
GType
|
||||
vips_foreign_tiff_compression_get_type( void )
|
||||
{
|
||||
static GType etype = 0;
|
||||
|
Loading…
Reference in New Issue
Block a user