diff --git a/libvips/foreign/vips2webp.c b/libvips/foreign/vips2webp.c index 3c60f0c6..e7186b68 100644 --- a/libvips/foreign/vips2webp.c +++ b/libvips/foreign/vips2webp.c @@ -55,10 +55,13 @@ typedef size_t (*webp_encoder)( const uint8_t *rgb, int width, int height, int stride, float quality_factor, uint8_t **output ); +typedef size_t (*webp_encoder_lossless)( const uint8_t *rgb, + int width, int height, int stride, uint8_t **output ); + int -vips__webp_write_file( VipsImage *in, const char *filename, int Q ) +vips__webp_write_file( VipsImage *in, const char *filename, + int Q, gboolean lossless ) { - webp_encoder encoder; size_t len; uint8_t *buffer; FILE *fp; @@ -66,17 +69,39 @@ vips__webp_write_file( VipsImage *in, const char *filename, int Q ) if( vips_image_wio_input( in ) ) return( -1 ); - if( in->Bands == 4 ) - encoder = WebPEncodeRGBA; - else - encoder = WebPEncodeRGB; + if( lossless ) { + webp_encoder_lossless encoder; - if( !(len = encoder( VIPS_IMAGE_ADDR( in, 0, 0 ), - in->Xsize, in->Ysize, - VIPS_IMAGE_SIZEOF_LINE( in ), - Q, &buffer )) ) { - vips_error( "vips2webp", "%s", _( "unable to encode" ) ); - return( -1 ); + if( in->Bands == 4 ) + encoder = WebPEncodeLosslessRGBA; + else + encoder = WebPEncodeLosslessRGB; + + if( !(len = encoder( VIPS_IMAGE_ADDR( in, 0, 0 ), + in->Xsize, in->Ysize, + VIPS_IMAGE_SIZEOF_LINE( in ), + &buffer )) ) { + vips_error( "vips2webp", + "%s", _( "unable to encode" ) ); + return( -1 ); + } + } + else { + webp_encoder encoder; + + if( in->Bands == 4 ) + encoder = WebPEncodeRGBA; + else + encoder = WebPEncodeRGB; + + if( !(len = encoder( VIPS_IMAGE_ADDR( in, 0, 0 ), + in->Xsize, in->Ysize, + VIPS_IMAGE_SIZEOF_LINE( in ), + Q, &buffer )) ) { + vips_error( "vips2webp", + "%s", _( "unable to encode" ) ); + return( -1 ); + } } if( !(fp = vips__file_open_write( filename, FALSE )) ) { @@ -97,7 +122,8 @@ vips__webp_write_file( VipsImage *in, const char *filename, int Q ) } int -vips__webp_write_buffer( VipsImage *in, void **obuf, size_t *olen, int Q ) +vips__webp_write_buffer( VipsImage *in, void **obuf, size_t *olen, + int Q, gboolean lossless ) { webp_encoder encoder; diff --git a/libvips/foreign/webp.h b/libvips/foreign/webp.h index e5b7f8a4..7441b893 100644 --- a/libvips/foreign/webp.h +++ b/libvips/foreign/webp.h @@ -45,8 +45,10 @@ int vips__webp_read_file( const char *name, VipsImage *out ); int vips__webp_read_buffer_header( void *buf, size_t len, VipsImage *out ); int vips__webp_read_buffer( void *buf, size_t len, VipsImage *out ); -int vips__webp_write_file( VipsImage *out, const char *filename, int Q ); -int vips__webp_write_buffer( VipsImage *out, void **buf, size_t *len, int Q ); +int vips__webp_write_file( VipsImage *out, const char *filename, + int Q, gboolean lossless ); +int vips__webp_write_buffer( VipsImage *out, void **buf, size_t *len, + int Q, gboolean lossless ); #ifdef __cplusplus } diff --git a/libvips/foreign/webpsave.c b/libvips/foreign/webpsave.c index 0f0c5cc8..432e6e96 100644 --- a/libvips/foreign/webpsave.c +++ b/libvips/foreign/webpsave.c @@ -56,6 +56,10 @@ typedef struct _VipsForeignSaveWebp { */ int Q; + /* Turn on lossless encode. + */ + gboolean lossless; + } VipsForeignSaveWebp; typedef VipsForeignSaveClass VipsForeignSaveWebpClass; @@ -95,6 +99,13 @@ vips_foreign_save_webp_class_init( VipsForeignSaveWebpClass *class ) G_STRUCT_OFFSET( VipsForeignSaveWebp, Q ), 1, 100, 75 ); + VIPS_ARG_BOOL( class, "lossless", 11, + _( "lossless" ), + _( "enable lossless compression" ), + VIPS_ARGUMENT_OPTIONAL_INPUT, + G_STRUCT_OFFSET( VipsForeignSaveWebp, lossless ), + FALSE ); + } static void @@ -128,7 +139,8 @@ vips_foreign_save_webp_file_build( VipsObject *object ) build( object ) ) return( -1 ); - if( vips__webp_write_file( save->ready, file->filename, webp->Q ) ) + if( vips__webp_write_file( save->ready, file->filename, + webp->Q, webp->lossless ) ) return( -1 ); return( 0 ); @@ -192,7 +204,8 @@ vips_foreign_save_webp_buffer_build( VipsObject *object ) build( object ) ) return( -1 ); - if( vips__webp_write_buffer( save->ready, &obuf, &olen, webp->Q ) ) + if( vips__webp_write_buffer( save->ready, &obuf, &olen, + webp->Q, webp->lossless ) ) return( -1 ); area = vips_area_new_blob( (VipsCallbackFn) vips_free, obuf, olen ); @@ -252,7 +265,8 @@ vips_foreign_save_webp_mime_build( VipsObject *object ) build( object ) ) return( -1 ); - if( vips__webp_write_buffer( save->ready, &obuf, &olen, webp->Q ) ) + if( vips__webp_write_buffer( save->ready, &obuf, &olen, + webp->Q, webp->lossless ) ) return( -1 ); printf( "Content-length: %zd\r\n", olen );