New webpsave option smart_subsample
This enables a high quality RGB to YUV converter in libwebp which greatly improves the quality of fine details by reducing color bleeding caused by the 4:2:0 chroma subsampling. This is slower and causes slightly larger files. See WebPPictureSmartARGBToYUVA in libwebp.
This commit is contained in:
parent
f834ea39f6
commit
58a2616f77
@ -2460,6 +2460,7 @@ vips_webpload_buffer( void *buf, size_t len, VipsImage **out, ... )
|
||||
* @Q: quality factor
|
||||
* @lossless: enables lossless compression
|
||||
* @preset: #VipsForeignWebpPreset choose lossy compression preset
|
||||
* @smart_subsample: enables high quality chroma subsampling
|
||||
*
|
||||
* See also: vips_webpload(), vips_image_write_to_file().
|
||||
*
|
||||
@ -2490,6 +2491,7 @@ vips_webpsave( VipsImage *in, const char *filename, ... )
|
||||
* @Q: JPEG quality factor
|
||||
* @lossless: enables lossless compression
|
||||
* @preset: #VipsForeignWebpPreset choose lossy compression preset
|
||||
* @smart_subsample: enables high quality chroma subsampling
|
||||
*
|
||||
* See also: vips_webpsave().
|
||||
*
|
||||
|
@ -84,7 +84,8 @@ get_preset( VipsForeignWebpPreset preset )
|
||||
|
||||
static int
|
||||
write_webp( WebPPicture *pic, VipsImage *in,
|
||||
int Q, gboolean lossless, VipsForeignWebpPreset preset )
|
||||
int Q, gboolean lossless, VipsForeignWebpPreset preset,
|
||||
gboolean smart_subsample )
|
||||
{
|
||||
VipsImage *memory;
|
||||
WebPConfig config;
|
||||
@ -97,6 +98,8 @@ write_webp( WebPPicture *pic, VipsImage *in,
|
||||
}
|
||||
|
||||
config.lossless = lossless;
|
||||
if( smart_subsample )
|
||||
config.preprocessing |= 4;
|
||||
|
||||
if( !WebPValidateConfig(&config) ) {
|
||||
vips_error( "vips2webp",
|
||||
@ -107,7 +110,10 @@ write_webp( WebPPicture *pic, VipsImage *in,
|
||||
if( !(memory = vips_image_copy_memory( in )) )
|
||||
return( -1 );
|
||||
|
||||
pic->use_argb = lossless;
|
||||
/* Smart subsampling requires use_argb because
|
||||
* it is applied during RGB to YUV conversion.
|
||||
*/
|
||||
pic->use_argb = lossless || smart_subsample;
|
||||
pic->width = memory->Xsize;
|
||||
pic->height = memory->Ysize;
|
||||
|
||||
@ -138,7 +144,8 @@ write_webp( WebPPicture *pic, VipsImage *in,
|
||||
|
||||
int
|
||||
vips__webp_write_file( VipsImage *in, const char *filename,
|
||||
int Q, gboolean lossless, VipsForeignWebpPreset preset )
|
||||
int Q, gboolean lossless, VipsForeignWebpPreset preset,
|
||||
gboolean smart_subsample )
|
||||
{
|
||||
WebPPicture pic;
|
||||
WebPMemoryWriter writer;
|
||||
@ -154,7 +161,7 @@ vips__webp_write_file( VipsImage *in, const char *filename,
|
||||
pic.writer = WebPMemoryWrite;
|
||||
pic.custom_ptr = &writer;
|
||||
|
||||
if( write_webp( &pic, in, Q, lossless, preset ) ) {
|
||||
if( write_webp( &pic, in, Q, lossless, preset, smart_subsample ) ) {
|
||||
WebPPictureFree( &pic );
|
||||
WebPMemoryWriterClear( &writer );
|
||||
return -1;
|
||||
@ -181,7 +188,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 )
|
||||
int Q, gboolean lossless, VipsForeignWebpPreset preset,
|
||||
gboolean smart_subsample )
|
||||
{
|
||||
WebPPicture pic;
|
||||
WebPMemoryWriter writer;
|
||||
@ -197,7 +205,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, preset ) ) {
|
||||
if( write_webp( &pic, in, Q, lossless, preset, smart_subsample ) ) {
|
||||
WebPPictureFree( &pic );
|
||||
WebPMemoryWriterClear( &writer );
|
||||
return -1;
|
||||
|
@ -49,9 +49,11 @@ 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, VipsForeignWebpPreset preset );
|
||||
int Q, gboolean lossless, VipsForeignWebpPreset preset,
|
||||
gboolean smart_subsample );
|
||||
int vips__webp_write_buffer( VipsImage *out, void **buf, size_t *len,
|
||||
int Q, gboolean lossless, VipsForeignWebpPreset preset );
|
||||
int Q, gboolean lossless, VipsForeignWebpPreset preset,
|
||||
gboolean smart_subsample );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -64,6 +64,10 @@ typedef struct _VipsForeignSaveWebp {
|
||||
*/
|
||||
VipsForeignWebpPreset preset;
|
||||
|
||||
/* Enable smart chroma subsampling.
|
||||
*/
|
||||
gboolean smart_subsample;
|
||||
|
||||
} VipsForeignSaveWebp;
|
||||
|
||||
typedef VipsForeignSaveClass VipsForeignSaveWebpClass;
|
||||
@ -121,6 +125,13 @@ vips_foreign_save_webp_class_init( VipsForeignSaveWebpClass *class )
|
||||
VIPS_TYPE_FOREIGN_WEBP_PRESET,
|
||||
VIPS_FOREIGN_WEBP_PRESET_DEFAULT );
|
||||
|
||||
VIPS_ARG_BOOL( class, "smart_subsample", 13,
|
||||
_( "Smart subsampling" ),
|
||||
_( "Enable high quality chroma subsampling" ),
|
||||
VIPS_ARGUMENT_OPTIONAL_INPUT,
|
||||
G_STRUCT_OFFSET( VipsForeignSaveWebp, smart_subsample ),
|
||||
FALSE );
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
@ -155,7 +166,8 @@ vips_foreign_save_webp_file_build( VipsObject *object )
|
||||
return( -1 );
|
||||
|
||||
if( vips__webp_write_file( save->ready, file->filename,
|
||||
webp->Q, webp->lossless, webp->preset ) )
|
||||
webp->Q, webp->lossless, webp->preset,
|
||||
webp->smart_subsample ) )
|
||||
return( -1 );
|
||||
|
||||
return( 0 );
|
||||
@ -217,7 +229,8 @@ vips_foreign_save_webp_buffer_build( VipsObject *object )
|
||||
return( -1 );
|
||||
|
||||
if( vips__webp_write_buffer( save->ready, &obuf, &olen,
|
||||
webp->Q, webp->lossless, webp->preset ) )
|
||||
webp->Q, webp->lossless, webp->preset,
|
||||
webp->smart_subsample ) )
|
||||
return( -1 );
|
||||
|
||||
blob = vips_blob_new( (VipsCallbackFn) vips_free, obuf, olen );
|
||||
@ -278,7 +291,8 @@ vips_foreign_save_webp_mime_build( VipsObject *object )
|
||||
return( -1 );
|
||||
|
||||
if( vips__webp_write_buffer( save->ready, &obuf, &olen,
|
||||
webp->Q, webp->lossless, webp->preset ) )
|
||||
webp->Q, webp->lossless, webp->preset,
|
||||
webp->smart_subsample ) )
|
||||
return( -1 );
|
||||
|
||||
printf( "Content-length: %zu\r\n", olen );
|
||||
|
Loading…
Reference in New Issue
Block a user