From 0a25f6efca64bf149253b0031c0d5ad9f80900b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20Bu=CC=88nemann?= Date: Sat, 23 Apr 2016 02:41:59 +0200 Subject: [PATCH] Add alpha_q(uality) webpsave option, fix Q init This allows to control the fidelity of the alpha channel by allowing webp to reduce the number of palette entries from 256 at alpha_q=100 to 2 at alpha_q=0. This is most useful with cutout pictures where something like alpha_q=30 or around 8 levels is usually sufficient for smooth outlines. For some reason webp->Q was intiailized to 80 even though the Q option and libwebp use 75 by default. This was never used, so it's just to avoid confusion about what default is used. --- libvips/foreign/foreign.c | 2 ++ libvips/foreign/vips2webp.c | 14 +++++++++----- libvips/foreign/webp.h | 6 ++++-- libvips/foreign/webpsave.c | 22 ++++++++++++++++++---- 4 files changed, 33 insertions(+), 11 deletions(-) diff --git a/libvips/foreign/foreign.c b/libvips/foreign/foreign.c index d6000680..fa371a73 100644 --- a/libvips/foreign/foreign.c +++ b/libvips/foreign/foreign.c @@ -2462,6 +2462,7 @@ vips_webpload_buffer( void *buf, size_t len, VipsImage **out, ... ) * @preset: #VipsForeignWebpPreset choose lossy compression preset * @smart_subsample: enables high quality chroma subsampling * @near_lossless: use preprocessing in lossless mode (controlled by Q) + * @alpha_q: set alpha quality in lossless mode * * See also: vips_webpload(), vips_image_write_to_file(). * @@ -2494,6 +2495,7 @@ vips_webpsave( VipsImage *in, const char *filename, ... ) * @preset: #VipsForeignWebpPreset choose lossy compression preset * @smart_subsample: enables high quality chroma subsampling * @near_lossless: use preprocessing in lossless mode (controlled by Q) + * @alpha_q: set alpha quality in lossless mode * * See also: vips_webpsave(). * diff --git a/libvips/foreign/vips2webp.c b/libvips/foreign/vips2webp.c index e8661cdd..1bc5787d 100644 --- a/libvips/foreign/vips2webp.c +++ b/libvips/foreign/vips2webp.c @@ -85,7 +85,8 @@ get_preset( VipsForeignWebpPreset preset ) static int write_webp( WebPPicture *pic, VipsImage *in, int Q, gboolean lossless, VipsForeignWebpPreset preset, - gboolean smart_subsample, gboolean near_lossless ) + gboolean smart_subsample, gboolean near_lossless, + int alpha_q ) { VipsImage *memory; WebPConfig config; @@ -102,6 +103,7 @@ write_webp( WebPPicture *pic, VipsImage *in, config.preprocessing |= 4; if( near_lossless ) config.near_lossless = Q; + config.alpha_quality = alpha_q; if( !WebPValidateConfig(&config) ) { vips_error( "vips2webp", @@ -147,7 +149,8 @@ write_webp( WebPPicture *pic, VipsImage *in, int vips__webp_write_file( VipsImage *in, const char *filename, int Q, gboolean lossless, VipsForeignWebpPreset preset, - gboolean smart_subsample, gboolean near_lossless ) + gboolean smart_subsample, gboolean near_lossless, + int alpha_q ) { WebPPicture pic; WebPMemoryWriter writer; @@ -164,7 +167,7 @@ vips__webp_write_file( VipsImage *in, const char *filename, pic.custom_ptr = &writer; if( write_webp( &pic, in, Q, lossless, preset, smart_subsample, - near_lossless ) ) { + near_lossless, alpha_q ) ) { WebPPictureFree( &pic ); WebPMemoryWriterClear( &writer ); return -1; @@ -192,7 +195,8 @@ 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, VipsForeignWebpPreset preset, - gboolean smart_subsample, gboolean near_lossless ) + gboolean smart_subsample, gboolean near_lossless, + int alpha_q ) { WebPPicture pic; WebPMemoryWriter writer; @@ -209,7 +213,7 @@ vips__webp_write_buffer( VipsImage *in, void **obuf, size_t *olen, pic.custom_ptr = &writer; if( write_webp( &pic, in, Q, lossless, preset, smart_subsample, - near_lossless) ) { + near_lossless, alpha_q ) ) { WebPPictureFree( &pic ); WebPMemoryWriterClear( &writer ); return -1; diff --git a/libvips/foreign/webp.h b/libvips/foreign/webp.h index 500b22b5..37f126e8 100644 --- a/libvips/foreign/webp.h +++ b/libvips/foreign/webp.h @@ -50,10 +50,12 @@ int vips__webp_read_buffer( const void *buf, size_t len, int vips__webp_write_file( VipsImage *out, const char *filename, int Q, gboolean lossless, VipsForeignWebpPreset preset, - gboolean smart_subsample, gboolean near_lossless ); + gboolean smart_subsample, gboolean near_lossless, + int alpha_q ); int vips__webp_write_buffer( VipsImage *out, void **buf, size_t *len, int Q, gboolean lossless, VipsForeignWebpPreset preset, - gboolean smart_subsample, gboolean near_lossless ); + gboolean smart_subsample, gboolean near_lossless, + int alpha_q ); #ifdef __cplusplus } diff --git a/libvips/foreign/webpsave.c b/libvips/foreign/webpsave.c index 5989c300..f677ff0e 100644 --- a/libvips/foreign/webpsave.c +++ b/libvips/foreign/webpsave.c @@ -72,6 +72,10 @@ typedef struct _VipsForeignSaveWebp { */ gboolean near_lossless; + /* Alpha quality. + */ + int alpha_q; + } VipsForeignSaveWebp; typedef VipsForeignSaveClass VipsForeignSaveWebpClass; @@ -143,12 +147,19 @@ vips_foreign_save_webp_class_init( VipsForeignSaveWebpClass *class ) G_STRUCT_OFFSET( VipsForeignSaveWebp, near_lossless ), FALSE ); + VIPS_ARG_INT( class, "alpha_q", 15, + _( "Alpha quality" ), + _( "Change alpha plane fidelity for lossy compression" ), + VIPS_ARGUMENT_OPTIONAL_INPUT, + G_STRUCT_OFFSET( VipsForeignSaveWebp, alpha_q ), + 0, 100, 100 ); + } static void vips_foreign_save_webp_init( VipsForeignSaveWebp *webp ) { - webp->Q = 80; + webp->Q = 75; } typedef struct _VipsForeignSaveWebpFile { @@ -178,7 +189,8 @@ vips_foreign_save_webp_file_build( VipsObject *object ) if( vips__webp_write_file( save->ready, file->filename, webp->Q, webp->lossless, webp->preset, - webp->smart_subsample, webp->near_lossless ) ) + webp->smart_subsample, webp->near_lossless, + webp->alpha_q ) ) return( -1 ); return( 0 ); @@ -241,7 +253,8 @@ vips_foreign_save_webp_buffer_build( VipsObject *object ) if( vips__webp_write_buffer( save->ready, &obuf, &olen, webp->Q, webp->lossless, webp->preset, - webp->smart_subsample, webp->near_lossless ) ) + webp->smart_subsample, webp->near_lossless, + webp->alpha_q ) ) return( -1 ); blob = vips_blob_new( (VipsCallbackFn) vips_free, obuf, olen ); @@ -303,7 +316,8 @@ vips_foreign_save_webp_mime_build( VipsObject *object ) if( vips__webp_write_buffer( save->ready, &obuf, &olen, webp->Q, webp->lossless, webp->preset, - webp->smart_subsample, webp->near_lossless ) ) + webp->smart_subsample, webp->near_lossless, + webp->alpha_q ) ) return( -1 ); printf( "Content-length: %zu\r\n", olen );