From 7f70abd4ba35c36ce71021c1cc3d82c4ff566c3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20Bu=CC=88nemann?= Date: Fri, 22 Apr 2016 19:45:53 +0200 Subject: [PATCH 01/34] Use advanced WebP Encoding API This switch is required to enable encoder configuration. --- libvips/foreign/vips2webp.c | 184 +++++++++++++++++++----------------- 1 file changed, 95 insertions(+), 89 deletions(-) diff --git a/libvips/foreign/vips2webp.c b/libvips/foreign/vips2webp.c index 52108cc8..b5b91a16 100644 --- a/libvips/foreign/vips2webp.c +++ b/libvips/foreign/vips2webp.c @@ -53,77 +53,102 @@ #include "webp.h" -typedef size_t (*webp_encoder)( const uint8_t *rgb, - int width, int height, int stride, - float quality_factor, uint8_t **output ); +typedef int (*webp_import)( WebPPicture *picture, + const uint8_t *rgb, int stride ); -typedef size_t (*webp_encoder_lossless)( const uint8_t *rgb, - int width, int height, int stride, uint8_t **output ); +static int +write_webp( WebPPicture *pic, VipsImage *in, + int Q, gboolean lossless ) +{ + VipsImage *memory; + WebPConfig config; + webp_import import; + + if ( !WebPConfigPreset(&config, WEBP_PRESET_DEFAULT, Q) ) { + vips_error( "vips2webp", + "%s", _( "config version error" ) ); + return( -1 ); + } + + config.lossless = lossless; + + if( !WebPValidateConfig(&config) ) { + vips_error( "vips2webp", + "%s", _( "invalid configuration" ) ); + return( -1 ); + } + + if( !(memory = vips_image_copy_memory( in )) ) + return( -1 ); + + pic->use_argb = lossless; + pic->width = memory->Xsize; + pic->height = memory->Ysize; + + if( in->Bands == 4 ) + import = WebPPictureImportRGBA; + else + import = WebPPictureImportRGB; + + if( !import( pic, VIPS_IMAGE_ADDR( memory, 0, 0 ), + VIPS_IMAGE_SIZEOF_LINE( memory ) ) ) { + VIPS_UNREF( memory ); + vips_error( "vips2webp", + "%s", _( "picture memory error" ) ); + return( -1 ); + } + + if( !WebPEncode( &config, pic ) ) { + VIPS_UNREF( memory ); + vips_error( "vips2webp", + "%s", _( "unable to encode" ) ); + return( -1 ); + } + + VIPS_UNREF( memory ); + + return( 0 ); +} int vips__webp_write_file( VipsImage *in, const char *filename, int Q, gboolean lossless ) { - VipsImage *memory; - size_t len; - uint8_t *buffer; + WebPPicture pic; + WebPMemoryWriter writer; FILE *fp; - if( !(memory = vips_image_copy_memory( in )) ) + if( !WebPPictureInit( &pic ) ) { + vips_error( "vips2webp", + "%s", _( "picture version error" ) ); return( -1 ); - - if( lossless ) { - webp_encoder_lossless encoder; - - if( in->Bands == 4 ) - encoder = WebPEncodeLosslessRGBA; - else - encoder = WebPEncodeLosslessRGB; - - if( !(len = encoder( VIPS_IMAGE_ADDR( memory, 0, 0 ), - memory->Xsize, memory->Ysize, - VIPS_IMAGE_SIZEOF_LINE( memory ), - &buffer )) ) { - VIPS_UNREF( memory ); - 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( memory, 0, 0 ), - memory->Xsize, memory->Ysize, - VIPS_IMAGE_SIZEOF_LINE( memory ), - Q, &buffer )) ) { - VIPS_UNREF( memory ); - vips_error( "vips2webp", - "%s", _( "unable to encode" ) ); - return( -1 ); - } } - VIPS_UNREF( memory ); + WebPMemoryWriterInit( &writer ); + pic.writer = WebPMemoryWrite; + pic.custom_ptr = &writer; + + if( write_webp( &pic, in, Q, lossless ) ) { + WebPPictureFree( &pic ); + WebPMemoryWriterClear( &writer ); + return -1; + } + + WebPPictureFree( &pic ); if( !(fp = vips__file_open_write( filename, FALSE )) ) { - free( buffer ); + WebPMemoryWriterClear( &writer ); return( -1 ); } - if( vips__file_write( buffer, len, 1, fp ) ) { + if( vips__file_write( writer.mem, writer.size, 1, fp ) ) { fclose( fp ); - free( buffer ); + WebPMemoryWriterClear( &writer ); return( -1 ); } fclose( fp ); - free( buffer ); + WebPMemoryWriterClear( &writer ); return( 0 ); } @@ -132,49 +157,30 @@ int vips__webp_write_buffer( VipsImage *in, void **obuf, size_t *olen, int Q, gboolean lossless ) { - VipsImage *memory; + WebPPicture pic; + WebPMemoryWriter writer; + FILE *fp; - if( !(memory = vips_image_copy_memory( in )) ) + if( !WebPPictureInit( &pic ) ) { + vips_error( "vips2webp", + "%s", _( "picture version error" ) ); return( -1 ); - - if( lossless ) { - webp_encoder_lossless encoder; - - if( in->Bands == 4 ) - encoder = WebPEncodeLosslessRGBA; - else - encoder = WebPEncodeLosslessRGB; - - if( !(*olen = encoder( VIPS_IMAGE_ADDR( memory, 0, 0 ), - memory->Xsize, memory->Ysize, - VIPS_IMAGE_SIZEOF_LINE( memory ), - (uint8_t **) obuf )) ) { - VIPS_UNREF( memory ); - vips_error( "vips2webp", - "%s", _( "unable to encode" ) ); - return( -1 ); - } - } - else { - webp_encoder encoder; - - if( in->Bands == 4 ) - encoder = WebPEncodeRGBA; - else - encoder = WebPEncodeRGB; - - if( !(*olen = encoder( VIPS_IMAGE_ADDR( memory, 0, 0 ), - memory->Xsize, memory->Ysize, - VIPS_IMAGE_SIZEOF_LINE( memory ), - Q, (uint8_t **) obuf )) ) { - VIPS_UNREF( memory ); - vips_error( "vips2webp", - "%s", _( "unable to encode" ) ); - return( -1 ); - } } - VIPS_UNREF( memory ); + WebPMemoryWriterInit( &writer ); + pic.writer = WebPMemoryWrite; + pic.custom_ptr = &writer; + + if( write_webp( &pic, in, Q, lossless ) ) { + WebPPictureFree( &pic ); + WebPMemoryWriterClear( &writer ); + return -1; + } + + WebPPictureFree( &pic ); + + *obuf = writer.mem; + *olen = writer.size; return( 0 ); } From f834ea39f6e9f35cf051352beba824529953c2ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20Bu=CC=88nemann?= Date: Fri, 22 Apr 2016 19:54:19 +0200 Subject: [PATCH 02/34] Add lossy compression "preset" option to webpsave This allows to tune the lossy webp encoder for certain types of images. --- libvips/foreign/foreign.c | 4 ++++ libvips/foreign/vips2webp.c | 38 +++++++++++++++++++++++++++----- libvips/foreign/webp.h | 4 ++-- libvips/foreign/webpsave.c | 18 ++++++++++++--- libvips/include/vips/enumtypes.h | 2 ++ libvips/include/vips/foreign.h | 23 +++++++++++++++++++ libvips/iofuncs/enumtypes.c | 22 ++++++++++++++++++ 7 files changed, 100 insertions(+), 11 deletions(-) diff --git a/libvips/foreign/foreign.c b/libvips/foreign/foreign.c index dd60b94b..a304ce08 100644 --- a/libvips/foreign/foreign.c +++ b/libvips/foreign/foreign.c @@ -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(). * diff --git a/libvips/foreign/vips2webp.c b/libvips/foreign/vips2webp.c index b5b91a16..6c7cab42 100644 --- a/libvips/foreign/vips2webp.c +++ b/libvips/foreign/vips2webp.c @@ -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; diff --git a/libvips/foreign/webp.h b/libvips/foreign/webp.h index 83e8653b..e1698239 100644 --- a/libvips/foreign/webp.h +++ b/libvips/foreign/webp.h @@ -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 } diff --git a/libvips/foreign/webpsave.c b/libvips/foreign/webpsave.c index b507785a..2b411d21 100644 --- a/libvips/foreign/webpsave.c +++ b/libvips/foreign/webpsave.c @@ -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 ); diff --git a/libvips/include/vips/enumtypes.h b/libvips/include/vips/enumtypes.h index 8fdc127a..f1b132fc 100644 --- a/libvips/include/vips/enumtypes.h +++ b/libvips/include/vips/enumtypes.h @@ -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; diff --git a/libvips/include/vips/foreign.h b/libvips/include/vips/foreign.h index 36328f43..a3a9af8e 100644 --- a/libvips/include/vips/foreign.h +++ b/libvips/include/vips/foreign.h @@ -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, ... ) diff --git a/libvips/iofuncs/enumtypes.c b/libvips/iofuncs/enumtypes.c index 4fb8062f..93f4564e 100644 --- a/libvips/iofuncs/enumtypes.c +++ b/libvips/iofuncs/enumtypes.c @@ -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; From 58a2616f77e69870f2f2969c97bc1e2cb9886187 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20Bu=CC=88nemann?= Date: Sat, 23 Apr 2016 01:20:41 +0200 Subject: [PATCH 03/34] 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. --- libvips/foreign/foreign.c | 2 ++ libvips/foreign/vips2webp.c | 20 ++++++++++++++------ libvips/foreign/webp.h | 6 ++++-- libvips/foreign/webpsave.c | 20 +++++++++++++++++--- 4 files changed, 37 insertions(+), 11 deletions(-) diff --git a/libvips/foreign/foreign.c b/libvips/foreign/foreign.c index a304ce08..c97c2d10 100644 --- a/libvips/foreign/foreign.c +++ b/libvips/foreign/foreign.c @@ -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(). * diff --git a/libvips/foreign/vips2webp.c b/libvips/foreign/vips2webp.c index 6c7cab42..c0505f67 100644 --- a/libvips/foreign/vips2webp.c +++ b/libvips/foreign/vips2webp.c @@ -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; diff --git a/libvips/foreign/webp.h b/libvips/foreign/webp.h index e1698239..0d934198 100644 --- a/libvips/foreign/webp.h +++ b/libvips/foreign/webp.h @@ -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 } diff --git a/libvips/foreign/webpsave.c b/libvips/foreign/webpsave.c index 2b411d21..29e647c7 100644 --- a/libvips/foreign/webpsave.c +++ b/libvips/foreign/webpsave.c @@ -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 ); From c107066c4e69cc26e1ade838a8185572567fe94f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20Bu=CC=88nemann?= Date: Sat, 23 Apr 2016 02:00:32 +0200 Subject: [PATCH 04/34] Add webpsave near_lossless support, fix Q range The near_lossless option allows to enable preprocessing for the lossless mode. This is a boolean instead of an int, because the amount of preprocessing is controlled using the Q factor parameter which is otherwise unused in lossless mode. This allows to re-use the quality setting in existing tools. --- libvips/foreign/foreign.c | 2 ++ libvips/foreign/vips2webp.c | 18 +++++++++++------- libvips/foreign/webp.h | 4 ++-- libvips/foreign/webpsave.c | 19 +++++++++++++++---- 4 files changed, 30 insertions(+), 13 deletions(-) diff --git a/libvips/foreign/foreign.c b/libvips/foreign/foreign.c index c97c2d10..d6000680 100644 --- a/libvips/foreign/foreign.c +++ b/libvips/foreign/foreign.c @@ -2461,6 +2461,7 @@ vips_webpload_buffer( void *buf, size_t len, VipsImage **out, ... ) * @lossless: enables lossless compression * @preset: #VipsForeignWebpPreset choose lossy compression preset * @smart_subsample: enables high quality chroma subsampling + * @near_lossless: use preprocessing in lossless mode (controlled by Q) * * See also: vips_webpload(), vips_image_write_to_file(). * @@ -2492,6 +2493,7 @@ vips_webpsave( VipsImage *in, const char *filename, ... ) * @lossless: enables lossless compression * @preset: #VipsForeignWebpPreset choose lossy compression preset * @smart_subsample: enables high quality chroma subsampling + * @near_lossless: use preprocessing in lossless mode (controlled by Q) * * See also: vips_webpsave(). * diff --git a/libvips/foreign/vips2webp.c b/libvips/foreign/vips2webp.c index c0505f67..e8661cdd 100644 --- a/libvips/foreign/vips2webp.c +++ b/libvips/foreign/vips2webp.c @@ -85,7 +85,7 @@ get_preset( VipsForeignWebpPreset preset ) static int write_webp( WebPPicture *pic, VipsImage *in, int Q, gboolean lossless, VipsForeignWebpPreset preset, - gboolean smart_subsample ) + gboolean smart_subsample, gboolean near_lossless ) { VipsImage *memory; WebPConfig config; @@ -97,9 +97,11 @@ write_webp( WebPPicture *pic, VipsImage *in, return( -1 ); } - config.lossless = lossless; + config.lossless = lossless || near_lossless; if( smart_subsample ) config.preprocessing |= 4; + if( near_lossless ) + config.near_lossless = Q; if( !WebPValidateConfig(&config) ) { vips_error( "vips2webp", @@ -113,7 +115,7 @@ write_webp( WebPPicture *pic, VipsImage *in, /* Smart subsampling requires use_argb because * it is applied during RGB to YUV conversion. */ - pic->use_argb = lossless || smart_subsample; + pic->use_argb = lossless || near_lossless || smart_subsample; pic->width = memory->Xsize; pic->height = memory->Ysize; @@ -145,7 +147,7 @@ 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 smart_subsample, gboolean near_lossless ) { WebPPicture pic; WebPMemoryWriter writer; @@ -161,7 +163,8 @@ vips__webp_write_file( VipsImage *in, const char *filename, pic.writer = WebPMemoryWrite; pic.custom_ptr = &writer; - if( write_webp( &pic, in, Q, lossless, preset, smart_subsample ) ) { + if( write_webp( &pic, in, Q, lossless, preset, smart_subsample, + near_lossless ) ) { WebPPictureFree( &pic ); WebPMemoryWriterClear( &writer ); return -1; @@ -189,7 +192,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, VipsForeignWebpPreset preset, - gboolean smart_subsample ) + gboolean smart_subsample, gboolean near_lossless ) { WebPPicture pic; WebPMemoryWriter writer; @@ -205,7 +208,8 @@ 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, smart_subsample ) ) { + if( write_webp( &pic, in, Q, lossless, preset, smart_subsample, + near_lossless) ) { WebPPictureFree( &pic ); WebPMemoryWriterClear( &writer ); return -1; diff --git a/libvips/foreign/webp.h b/libvips/foreign/webp.h index 0d934198..500b22b5 100644 --- a/libvips/foreign/webp.h +++ b/libvips/foreign/webp.h @@ -50,10 +50,10 @@ 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 smart_subsample, gboolean near_lossless ); int vips__webp_write_buffer( VipsImage *out, void **buf, size_t *len, int Q, gboolean lossless, VipsForeignWebpPreset preset, - gboolean smart_subsample ); + gboolean smart_subsample, gboolean near_lossless ); #ifdef __cplusplus } diff --git a/libvips/foreign/webpsave.c b/libvips/foreign/webpsave.c index 29e647c7..5989c300 100644 --- a/libvips/foreign/webpsave.c +++ b/libvips/foreign/webpsave.c @@ -68,6 +68,10 @@ typedef struct _VipsForeignSaveWebp { */ gboolean smart_subsample; + /* Use preprocessing in lossless mode. + */ + gboolean near_lossless; + } VipsForeignSaveWebp; typedef VipsForeignSaveClass VipsForeignSaveWebpClass; @@ -108,7 +112,7 @@ vips_foreign_save_webp_class_init( VipsForeignSaveWebpClass *class ) _( "Q factor" ), VIPS_ARGUMENT_OPTIONAL_INPUT, G_STRUCT_OFFSET( VipsForeignSaveWebp, Q ), - 1, 100, 75 ); + 0, 100, 75 ); VIPS_ARG_BOOL( class, "lossless", 11, _( "lossless" ), @@ -132,6 +136,13 @@ vips_foreign_save_webp_class_init( VipsForeignSaveWebpClass *class ) G_STRUCT_OFFSET( VipsForeignSaveWebp, smart_subsample ), FALSE ); + VIPS_ARG_BOOL( class, "near_lossless", 14, + _( "Near lossless" ), + _( "Enable preprocessing in lossless mode (uses Q)" ), + VIPS_ARGUMENT_OPTIONAL_INPUT, + G_STRUCT_OFFSET( VipsForeignSaveWebp, near_lossless ), + FALSE ); + } static void @@ -167,7 +178,7 @@ 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->smart_subsample, webp->near_lossless ) ) return( -1 ); return( 0 ); @@ -230,7 +241,7 @@ 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->smart_subsample, webp->near_lossless ) ) return( -1 ); blob = vips_blob_new( (VipsCallbackFn) vips_free, obuf, olen ); @@ -292,7 +303,7 @@ 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->smart_subsample, webp->near_lossless ) ) return( -1 ); printf( "Content-length: %zu\r\n", olen ); 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 05/34] 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 ); From 874cc8b31bf99257d1ef0078711a451f79b625d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20Bu=CC=88nemann?= Date: Sat, 23 Apr 2016 07:00:42 +0200 Subject: [PATCH 06/34] Restore webpsave libwebp-0.1.3 compatility * Add configure check for libwebp >= 0.1.3 * Add custom memory writer using GNOME memory allocation * Add various ABI checks and warnings for unsupported features: ** smart_subsample and near_lossless require 0.5.0 ** lossless requires at least 0.1.99 --- configure.ac | 3 +- libvips/foreign/foreign.c | 6 +++ libvips/foreign/vips2webp.c | 105 +++++++++++++++++++++++++++++------- 3 files changed, 95 insertions(+), 19 deletions(-) diff --git a/configure.ac b/configure.ac index afd5f078..2d62bcd0 100644 --- a/configure.ac +++ b/configure.ac @@ -677,7 +677,7 @@ AC_ARG_WITH([libwebp], AS_HELP_STRING([--without-libwebp], [build without libwebp (default: test)])) if test x"$with_libwebp" != "xno"; then - PKG_CHECK_MODULES(LIBWEBP, libwebp, + PKG_CHECK_MODULES(LIBWEBP, libwebp >= 0.1.3, [AC_DEFINE(HAVE_LIBWEBP,1,[define if you have libwebp installed.]) with_libwebp=yes PACKAGES_USED="$PACKAGES_USED libwebp"], @@ -972,6 +972,7 @@ SVG import with librsvg-2.0: $with_rsvg (requires librsvg-2.0 2.40.0 or later) file import with cfitsio: $with_cfitsio file import/export with libwebp: $with_libwebp + (requires libwebp-0.1.3 or later) text rendering with pangoft2: $with_pangoft2 file import/export with libpng: $with_png (requires libpng-1.2.9 or later) diff --git a/libvips/foreign/foreign.c b/libvips/foreign/foreign.c index fa371a73..af037279 100644 --- a/libvips/foreign/foreign.c +++ b/libvips/foreign/foreign.c @@ -2497,6 +2497,12 @@ vips_webpsave( VipsImage *in, const char *filename, ... ) * @near_lossless: use preprocessing in lossless mode (controlled by Q) * @alpha_q: set alpha quality in lossless mode * + * As vips_webpsave(), but save to a memory buffer. + * + * The address of the buffer is returned in @obuf, the length of the buffer in + * @olen. You are responsible for freeing the buffer with g_free() when you + * are done with it. The buffer is freed for you on error. + * * See also: vips_webpsave(). * * Returns: 0 on success, -1 on error. diff --git a/libvips/foreign/vips2webp.c b/libvips/foreign/vips2webp.c index 1bc5787d..17726218 100644 --- a/libvips/foreign/vips2webp.c +++ b/libvips/foreign/vips2webp.c @@ -46,6 +46,7 @@ #ifdef HAVE_LIBWEBP #include +#include #include @@ -82,6 +83,55 @@ get_preset( VipsForeignWebpPreset preset ) return( -1 ); } +typedef struct { + uint8_t *mem; + size_t size; + size_t max_size; +} VipsWebPMemoryWriter; + +static void +init_memory_writer( VipsWebPMemoryWriter *writer ) { + writer->mem = NULL; + writer->size = 0; + writer->max_size = 0; +} + +static int +memory_write( const uint8_t *data, size_t data_size, + const WebPPicture *picture ) { + VipsWebPMemoryWriter* const w = (VipsWebPMemoryWriter*) picture->custom_ptr; + size_t next_size; + + if( w == NULL ) + return( 0 ); + + next_size = w->size + data_size; + + if( next_size > w->max_size ) { + uint8_t *new_mem; + const size_t next_max_size = + VIPS_MAX( 8192, VIPS_MAX( next_size, w->max_size * 2 ) ); + + new_mem = (uint8_t*) g_try_malloc( next_max_size ); + if( new_mem == NULL ) + return( 0 ); + + if( w->size > 0 ) + memcpy( new_mem, w->mem, w->size ); + + g_free( w->mem ); + w->mem = new_mem; + w->max_size = next_max_size; + } + + if( data_size > 0 ) { + memcpy( w->mem + w->size, data, data_size ); + w->size += data_size; + } + + return( 1 ); +} + static int write_webp( WebPPicture *pic, VipsImage *in, int Q, gboolean lossless, VipsForeignWebpPreset preset, @@ -98,12 +148,35 @@ write_webp( WebPPicture *pic, VipsImage *in, return( -1 ); } +#if WEBP_ENCODER_ABI_VERSION >= 0x0100 config.lossless = lossless || near_lossless; - if( smart_subsample ) - config.preprocessing |= 4; + config.alpha_quality = alpha_q; + /* Smart subsampling requires use_argb because + * it is applied during RGB to YUV conversion. + */ + pic->use_argb = lossless || near_lossless || smart_subsample; +#else + if( lossless || near_lossless ) + vips_warn( "vips2webp", + "%s", _( "lossless unsupported" ) ); + if( alpha_q != 100 ) + vips_warn( "vips2webp", + "%s", _( "alpha_q unsupported" ) ); +#endif + +#if WEBP_ENCODER_ABI_VERSION >= 0x0209 if( near_lossless ) config.near_lossless = Q; - config.alpha_quality = alpha_q; + if( smart_subsample ) + config.preprocessing |= 4; +#else + if( near_lossless ) + vips_warn( "vips2webp", + "%s", _( "near_lossless unsupported" ) ); + if( smart_subsample ) + vips_warn( "vips2webp", + "%s", _( "smart_subsample unsupported" ) ); +#endif if( !WebPValidateConfig(&config) ) { vips_error( "vips2webp", @@ -114,10 +187,6 @@ write_webp( WebPPicture *pic, VipsImage *in, if( !(memory = vips_image_copy_memory( in )) ) return( -1 ); - /* Smart subsampling requires use_argb because - * it is applied during RGB to YUV conversion. - */ - pic->use_argb = lossless || near_lossless || smart_subsample; pic->width = memory->Xsize; pic->height = memory->Ysize; @@ -153,7 +222,7 @@ vips__webp_write_file( VipsImage *in, const char *filename, int alpha_q ) { WebPPicture pic; - WebPMemoryWriter writer; + VipsWebPMemoryWriter writer; FILE *fp; if( !WebPPictureInit( &pic ) ) { @@ -162,32 +231,32 @@ vips__webp_write_file( VipsImage *in, const char *filename, return( -1 ); } - WebPMemoryWriterInit( &writer ); - pic.writer = WebPMemoryWrite; + init_memory_writer( &writer ); + pic.writer = memory_write; pic.custom_ptr = &writer; if( write_webp( &pic, in, Q, lossless, preset, smart_subsample, near_lossless, alpha_q ) ) { WebPPictureFree( &pic ); - WebPMemoryWriterClear( &writer ); + g_free( writer.mem ); return -1; } WebPPictureFree( &pic ); if( !(fp = vips__file_open_write( filename, FALSE )) ) { - WebPMemoryWriterClear( &writer ); + g_free( writer.mem ); return( -1 ); } if( vips__file_write( writer.mem, writer.size, 1, fp ) ) { fclose( fp ); - WebPMemoryWriterClear( &writer ); + g_free( writer.mem ); return( -1 ); } fclose( fp ); - WebPMemoryWriterClear( &writer ); + g_free( writer.mem ); return( 0 ); } @@ -199,7 +268,7 @@ vips__webp_write_buffer( VipsImage *in, void **obuf, size_t *olen, int alpha_q ) { WebPPicture pic; - WebPMemoryWriter writer; + VipsWebPMemoryWriter writer; FILE *fp; if( !WebPPictureInit( &pic ) ) { @@ -208,14 +277,14 @@ vips__webp_write_buffer( VipsImage *in, void **obuf, size_t *olen, return( -1 ); } - WebPMemoryWriterInit( &writer ); - pic.writer = WebPMemoryWrite; + init_memory_writer( &writer ); + pic.writer = memory_write; pic.custom_ptr = &writer; if( write_webp( &pic, in, Q, lossless, preset, smart_subsample, near_lossless, alpha_q ) ) { WebPPictureFree( &pic ); - WebPMemoryWriterClear( &writer ); + g_free( writer.mem ); return -1; } From 27e319883352f952f1bcf90dbc73dd8e66e2618c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20Bu=CC=88nemann?= Date: Sat, 23 Apr 2016 23:36:49 +0200 Subject: [PATCH 07/34] Add webp save/load format tests for "make check" --- test/test_formats.sh | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/test/test_formats.sh b/test/test_formats.sh index 28b0ba68..72af1ad4 100755 --- a/test/test_formats.sh +++ b/test/test_formats.sh @@ -186,6 +186,10 @@ fi if test_supported jpegload; then test_format $image jpg 90 fi +if test_supported webpload; then + test_format $image webp 90 + test_format $image webp 0 [lossless] +fi test_format $image ppm 0 test_format $image pfm 0 if test_supported fitsload; then @@ -220,4 +224,3 @@ if test_supported dzsave; then test_saver copy $image .dz test_saver copy $image .dz[container=zip] fi - From 73080bb4a5c219154b30faa4a97ab92336064a70 Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Tue, 26 Apr 2016 10:41:04 +0100 Subject: [PATCH 08/34] try to improve mozjpeg test save LIBS around test, test for ABI not header see https://github.com/jcupitt/libvips/issues/431 --- configure.ac | 52 +++++++++++++++++++++++----------------------------- 1 file changed, 23 insertions(+), 29 deletions(-) diff --git a/configure.ac b/configure.ac index 915b9b77..201a893e 100644 --- a/configure.ac +++ b/configure.ac @@ -439,66 +439,66 @@ fi if test x"$with_magick" != "xno"; then # we SetImageOption to disable some DICOM read processing, but that's only # in more recent imagemagicks and not in graphicsmagick - save_LIBS=$LIBS + save_LIBS="$LIBS" LIBS="$LIBS $MAGICK_LIBS" AC_CHECK_FUNCS(SetImageOption, AC_DEFINE(HAVE_SETIMAGEOPTION,1, [define if your magick has SetImageOption.])) - LIBS=$save_LIBS + LIBS="$save_LIBS" fi if test x"$with_magick" != "xno"; then # newer ImageMagicks use MagickCoreGenesis instead of InitializeMagick argh - save_LIBS=$LIBS + save_LIBS="$LIBS" LIBS="$LIBS $MAGICK_LIBS" AC_CHECK_FUNCS(MagickCoreGenesis, AC_DEFINE(HAVE_MAGICKCOREGENESIS,1, [define if your magick has MagickCoreGenesis.])) - LIBS=$save_LIBS + LIBS="$save_LIBS" fi if test x"$with_magick" != "xno"; then # newer ImageMagicks use ResetImagePropertyIterator instead of # ResetImageAttributeIterator argh - save_LIBS=$LIBS + save_LIBS="$LIBS" LIBS="$LIBS $MAGICK_LIBS" AC_CHECK_FUNCS(ResetImagePropertyIterator, AC_DEFINE(HAVE_RESETIMAGEPROPERTYITERATOR,1, [define if your magick has ResetImagePropertyIterator.])) - LIBS=$save_LIBS + LIBS="$save_LIBS" fi if test x"$with_magick" != "xno"; then # so ... do we have ResetImageAttributeIterator()? GM does not - save_LIBS=$LIBS + save_LIBS="$LIBS" LIBS="$LIBS $MAGICK_LIBS" AC_CHECK_FUNCS(ResetImageAttributeIterator, AC_DEFINE(HAVE_RESETIMAGEATTRIBUTEITERATOR,1, [define if your magick has ResetImageAttributeIterator.])) - LIBS=$save_LIBS + LIBS="$save_LIBS" fi if test x"$with_magick" != "xno"; then # more recent magicks have GetVirtualPixels rather than GetImagePixels - save_LIBS=$LIBS + save_LIBS="$LIBS" LIBS="$LIBS $MAGICK_LIBS" AC_CHECK_FUNCS(GetVirtualPixels, AC_DEFINE(HAVE_GETVIRTUALPIXELS,1, [define if your magick has GetVirtualPixels.])) - LIBS=$save_LIBS + LIBS="$save_LIBS" fi if test x"$with_magick" != "xno"; then # do we have number_scenes in image_info ... imagemagick uses this, gm # still uses subrange - save_CFLAGS=$CFLAGS + save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $MAGICK_CFLAGS" AC_CHECK_MEMBER([struct _ImageInfo.number_scenes], AC_DEFINE(HAVE_NUMBER_SCENES,1, [define if your magick has ImageInfo.number_scenes.]), [], [#include ]) - CFLAGS=$save_CFLAGS + CFLAGS="$save_CFLAGS" fi # orc @@ -511,12 +511,12 @@ if test x"$with_orc" != "xno"; then [AC_DEFINE(HAVE_ORC,1,[define if you have orc-0.4.11 or later installed.]) with_orc=yes PACKAGES_USED="$PACKAGES_USED orc-0.4" - save_LIBS=$LIBS + save_LIBS="$LIBS" LIBS="$LIBS $ORC_LIBS" AC_CHECK_FUNCS(orc_program_get_error, AC_DEFINE(HAVE_ORC_PROGRAM_GET_ERROR,1, [define if your orc has orc_program_get_error.])) - LIBS=$save_LIBS + LIBS="$save_LIBS" ], [AC_MSG_WARN([orc-0.4.11 or later not found; disabling orc support]) with_orc=no @@ -791,19 +791,13 @@ FIND_JPEG( ]) # JPEG extension parameters available in libjpeg-turbo >=1.5.0, mozjpeg >=3.0 -if test x"$with_jpeg" = "xyes"; then - AC_MSG_CHECKING([for JPEG extension parameters]) - AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ - #include - #include - ]], [[ - J_BOOLEAN_PARAM test; - ]])], [ - AC_MSG_RESULT([yes]) - AC_DEFINE([HAVE_JPEG_EXT_PARAMS],1,[libjpeg has extension parameters]) - ], [ - AC_MSG_RESULT([no]) - ]) +if test x"$with_jpeg" != "xno"; then + save_LIBS="$LIBS" + LIBS="$LIBS $JPEG_LIBS" + AC_CHECK_FUNCS(jpeg_c_bool_param_supported, + AC_DEFINE(HAVE_JPEG_EXT_PARAMS,1, + [define if your libjpeg has extension parameters.])) + LIBS="$save_LIBS" fi # libexif @@ -824,11 +818,11 @@ fi # how annoying if test x"$with_libexif" != "xno"; then # cppflags not cflags because we want the preproc to see the -I as well - save_CPPFLAGS=$CPPFLAGS + save_CPPFLAGS="$CPPFLAGS" CPPFLAGS="$EXIF_CFLAGS $CPPFLAGS" AC_CHECK_HEADER(exif-data.h, AC_DEFINE(UNTAGGED_EXIF,1,[libexif includes don't need libexif prefix])) - CPPFLAGS=$save_CPPFLAGS + CPPFLAGS="$save_CPPFLAGS" fi # make python binding? From c2d1de9a264cb71812bac1a5b0cb178807ddef0a Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Sun, 1 May 2016 12:03:13 +0100 Subject: [PATCH 09/34] allow mixed zoom and shrink in resize vips_resize() now allows >1 on one axis, <1 on the other ... previously, although you could have non-square ratios, you couldn't mix zoom and shrink --- ChangeLog | 1 + libvips/resample/resize.c | 58 ++++++++++++++++++++++++++------------- libvips/resample/shrink.c | 5 ++-- 3 files changed, 42 insertions(+), 22 deletions(-) diff --git a/ChangeLog b/ChangeLog index 57ed412e..68a2bea9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -3,6 +3,7 @@ - export C++ operator overloads for MSVC linking [Lovell] - fix magickload @page with GraphicsMagick - add giflib5 support +- allow resize >1 on one axis, <1 on the other 29/1/16 started 8.3 - add vips_reduce*() ... a fast path for affine downsize diff --git a/libvips/resample/resize.c b/libvips/resample/resize.c index 8cea30dd..95255538 100644 --- a/libvips/resample/resize.c +++ b/libvips/resample/resize.c @@ -10,6 +10,8 @@ * - shrink more affine less, now we have better anti-alias settings * 10/3/16 * - revise again, using new vips_reduce() code + * 1/5/16 + * - allow >1 on one axis, <1 on the other */ /* @@ -132,15 +134,20 @@ vips_resize_build( VipsObject *object ) else int_vshrink = int_hshrink; - if( int_hshrink > 1 || - int_vshrink > 1 ) { - vips_info( class->nickname, "box shrink by %d x %d", - int_hshrink, int_vshrink ); - if( vips_shrink( in, &t[0], int_hshrink, int_vshrink, NULL ) ) + if( int_vshrink > 1 ) { + vips_info( class->nickname, "shrinkv by %d", int_vshrink ); + if( vips_shrinkv( in, &t[0], int_vshrink, NULL ) ) return( -1 ); in = t[0]; } + if( int_hshrink > 1 ) { + vips_info( class->nickname, "shrinkh by %d", int_hshrink ); + if( vips_shrinkh( in, &t[1], int_hshrink, NULL ) ) + return( -1 ); + in = t[1]; + } + /* Do we need a further size adjustment? It's the difference * between our target size and the size we have after vips_shrink(). * @@ -195,30 +202,43 @@ vips_resize_build( VipsObject *object ) in = t[6]; } - /* Any downsizing. + /* Any residual downsizing. */ - if( hresidual < 1.0 || - vresidual < 1.0 ) { - vips_info( class->nickname, "residual reduce by %g x %g", - hresidual, vresidual ); - - if( vips_reduce( in, &t[2], - 1.0 / hresidual, 1.0 / vresidual, NULL ) ) + if( vresidual < 1.0 ) { + vips_info( class->nickname, "residual reducev by %g", + vresidual ); + if( vips_reducev( in, &t[2], 1.0 / vresidual, NULL ) ) return( -1 ); in = t[2]; } + if( hresidual < 1.0 ) { + vips_info( class->nickname, "residual reduceh by %g", + hresidual ); + if( vips_reduceh( in, &t[3], 1.0 / hresidual, NULL ) ) + return( -1 ); + in = t[3]; + } + /* Any upsizing. */ - if( hresidual > 1.0 || - vresidual > 1.0 ) { - vips_info( class->nickname, "residual scale %g x %g", - hresidual, vresidual ); - if( vips_affine( in, &t[3], hresidual, 0, 0, vresidual, + if( hresidual > 1.0 ) { + vips_info( class->nickname, "residual scaleh %g", + hresidual ); + if( vips_affine( in, &t[4], hresidual, 0.0, 0.0, 1.0, "interpolate", vips_interpolate_nearest_static(), NULL ) ) return( -1 ); - in = t[3]; + in = t[4]; + } + + if( vresidual > 1.0 ) { + vips_info( class->nickname, "residual scalev %g", vresidual ); + if( vips_affine( in, &t[5], 1.0, 0.0, 0.0, vresidual, + "interpolate", vips_interpolate_nearest_static(), + NULL ) ) + return( -1 ); + in = t[5]; } if( vips_image_write( in, resample->out ) ) diff --git a/libvips/resample/shrink.c b/libvips/resample/shrink.c index b329daa5..59efc483 100644 --- a/libvips/resample/shrink.c +++ b/libvips/resample/shrink.c @@ -99,13 +99,12 @@ vips_shrink_build( VipsObject *object ) yresidual = (double) target_height / t[1]->Ysize; if( vips_affine( t[1], &t[2], - xresidual, 0.0, 0.0, yresidual, NULL ) || + xresidual, 0.0, 0.0, yresidual, NULL ) || vips_image_write( t[2], resample->out ) ) return( -1 ); } else { - if( vips_shrinkv( resample->in, &t[0], - shrink->yshrink, NULL ) || + if( vips_shrinkv( resample->in, &t[0], shrink->yshrink, NULL ) || vips_shrinkh( t[0], &t[1], shrink->xshrink, NULL ) || vips_image_write( t[1], resample->out ) ) return( -1 ); From 02821ae9e3b5de6162552e5f6f953b354c89b643 Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Sun, 1 May 2016 12:33:49 +0100 Subject: [PATCH 10/34] expose @kernel setting for vips_resize() a new optional arg lets you pick the downsizing kernel --- ChangeLog | 1 + libvips/resample/resize.c | 31 +++++++++++++++++++++++++------ 2 files changed, 26 insertions(+), 6 deletions(-) diff --git a/ChangeLog b/ChangeLog index 68a2bea9..cbb50c50 100644 --- a/ChangeLog +++ b/ChangeLog @@ -4,6 +4,7 @@ - fix magickload @page with GraphicsMagick - add giflib5 support - allow resize >1 on one axis, <1 on the other +- vips_resize has an optional @kernel argument 29/1/16 started 8.3 - add vips_reduce*() ... a fast path for affine downsize diff --git a/libvips/resample/resize.c b/libvips/resample/resize.c index 95255538..bff34d7c 100644 --- a/libvips/resample/resize.c +++ b/libvips/resample/resize.c @@ -12,6 +12,7 @@ * - revise again, using new vips_reduce() code * 1/5/16 * - allow >1 on one axis, <1 on the other + * - expose @kernel setting */ /* @@ -69,6 +70,7 @@ typedef struct _VipsResize { double scale; double vscale; + VipsKernel kernel; /* Deprecated. */ @@ -207,7 +209,9 @@ vips_resize_build( VipsObject *object ) if( vresidual < 1.0 ) { vips_info( class->nickname, "residual reducev by %g", vresidual ); - if( vips_reducev( in, &t[2], 1.0 / vresidual, NULL ) ) + if( vips_reducev( in, &t[2], 1.0 / vresidual, + "kernel", resize->kernel, + NULL ) ) return( -1 ); in = t[2]; } @@ -215,7 +219,9 @@ vips_resize_build( VipsObject *object ) if( hresidual < 1.0 ) { vips_info( class->nickname, "residual reduceh by %g", hresidual ); - if( vips_reduceh( in, &t[3], 1.0 / hresidual, NULL ) ) + if( vips_reduceh( in, &t[3], 1.0 / hresidual, + "kernel", resize->kernel, + NULL ) ) return( -1 ); in = t[3]; } @@ -279,6 +285,13 @@ vips_resize_class_init( VipsResizeClass *class ) G_STRUCT_OFFSET( VipsResize, vscale ), 0, 10000000, 0 ); + VIPS_ARG_ENUM( class, "kernel", 3, + _( "Kernel" ), + _( "Resampling kernel" ), + VIPS_ARGUMENT_OPTIONAL_INPUT, + G_STRUCT_OFFSET( VipsResize, kernel ), + VIPS_TYPE_KERNEL, VIPS_KERNEL_LANCZOS3 ); + /* We used to let people set the input offset so you could pick centre * or corner interpolation, but it's not clear this was useful. */ @@ -311,6 +324,7 @@ vips_resize_class_init( VipsResizeClass *class ) static void vips_resize_init( VipsResize *resize ) { + resize->kernel = VIPS_KERNEL_LANCZOS3; } /** @@ -323,21 +337,26 @@ vips_resize_init( VipsResize *resize ) * Optional arguments: * * @vscale: vertical scale factor + * @kernel: #VipsKernel to reduce with * * Resize an image. When upsizing (@scale > 1), the image is simply block * upsized. When downsizing, the - * image is block-shrunk with vips_shrink(), then an anti-alias blur is - * applied with vips_gaussblur(), then the image is shrunk again to the - * target size with vips_reduce(). + * image is block-shrunk with vips_shrink(), + * then the image is shrunk again to the + * target size with vips_reduce(). The operation will leave at least the final + * x2 to be done with vips_reduce(). * * vips_resize() normally maintains the image apect ratio. If you set * @vscale, that factor is used for the vertical scale and @scale for the * horizontal. * + * vips_resize() normally uses #VIPS_KERNEL_LANCZOS3 for thre final shrink, you + * can change this with @kernel. + * * This operation does not change xres or yres. The image resolution needs to * be updated by the application. * - * See also: vips_shrink(), vips_reduce(), vips_gaussblur(). + * See also: vips_shrink(), vips_reduce(). * * Returns: 0 on success, -1 on error */ From 48ef2154790289fe3a4802f9313b83e7342fa7be Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Mon, 2 May 2016 09:55:16 +0100 Subject: [PATCH 11/34] tiny fixups for the webp commit just small formatting changes, plus an unneeded var see https://github.com/jcupitt/libvips/pull/430 --- ChangeLog | 3 +++ TODO | 2 ++ configure.ac | 8 +++--- libvips/foreign/foreign.c | 46 ++++++++++++++++++++++++---------- libvips/foreign/vips2webp.c | 37 ++++++++++++++------------- libvips/include/vips/foreign.h | 6 ++--- 6 files changed, 64 insertions(+), 38 deletions(-) diff --git a/ChangeLog b/ChangeLog index cbb50c50..859045b4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,6 @@ +1/5/16 started 8.4 +- many more wepsave options [Felix Bünemann] + 15/4/16 started 8.3.1 - rename vips wrapper script, it was still vips-8.2, thanks Benjamin - export C++ operator overloads for MSVC linking [Lovell] diff --git a/TODO b/TODO index cf0dcd7a..c16cf38d 100644 --- a/TODO +++ b/TODO @@ -1,3 +1,5 @@ +- add "*" before each optional arg description + - I like the new int mask creator in reducev, can we use it in im_vips2imask() as well? diff --git a/configure.ac b/configure.ac index 3bdf4466..4ddb37fe 100644 --- a/configure.ac +++ b/configure.ac @@ -2,7 +2,7 @@ # also update the version number in the m4 macros below -AC_INIT([vips], [8.3.1], [vipsip@jiscmail.ac.uk]) +AC_INIT([vips], [8.4.0], [vipsip@jiscmail.ac.uk]) # required for gobject-introspection AC_PREREQ(2.62) @@ -17,8 +17,8 @@ AC_CONFIG_MACRO_DIR([m4]) # user-visible library versioning m4_define([vips_major_version], [8]) -m4_define([vips_minor_version], [3]) -m4_define([vips_micro_version], [1]) +m4_define([vips_minor_version], [4]) +m4_define([vips_micro_version], [0]) m4_define([vips_version], [vips_major_version.vips_minor_version.vips_micro_version]) @@ -38,7 +38,7 @@ VIPS_VERSION_STRING=$VIPS_VERSION-`date` # binary interface changes not backwards compatible?: reset age to 0 LIBRARY_CURRENT=46 -LIBRARY_REVISION=1 +LIBRARY_REVISION=2 LIBRARY_AGE=4 # patched into include/vips/version.h diff --git a/libvips/foreign/foreign.c b/libvips/foreign/foreign.c index e012cb2f..2b7cffdc 100644 --- a/libvips/foreign/foreign.c +++ b/libvips/foreign/foreign.c @@ -2457,12 +2457,27 @@ 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 - * @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 + * * @Q: %gint quality factor + * * @lossless: %gboolean enables lossless compression + * * @preset: #VipsForeignWebpPreset choose lossy compression preset + * * @smart_subsample: %gboolean enables high quality chroma subsampling + * * @near_lossless: %gboolean use preprocessing in lossless mode (controlled by Q) + * * @alpha_q: %gint set alpha quality in lossless mode + * + * Write an image to a file in WebP format. + * + * Use @Q to set the WebP quality factor. It has the range 0 - 100, with the + * default 75. + * + * Use @preset to hint the image type to lossy compressor. The default is + * #VIPS_FOREIGN_WEBP_PRESET_DEFAULT. + * + * Set @smart_subsample to enable high quality chroma subsampling. + * + * Use @alpha_q to set the quality for the alpha channel in lossy mode. It has + * the range 1 - 100, with the default 100. + * + * Set @lossless to enable lossless save. * * See also: vips_webpload(), vips_image_write_to_file(). * @@ -2490,18 +2505,18 @@ vips_webpsave( VipsImage *in, const char *filename, ... ) * * Optional arguments: * - * @Q: JPEG quality factor - * @lossless: enables lossless compression + * @Q: %gint quality factor + * @lossless: %gboolean enables lossless compression * @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 + * @smart_subsample: %gboolean enables high quality chroma subsampling + * @near_lossless: %gboolean use preprocessing in lossless mode (controlled by Q) + * @alpha_q: %gint set alpha quality in lossless mode * * As vips_webpsave(), but save to a memory buffer. * * The address of the buffer is returned in @obuf, the length of the buffer in * @olen. You are responsible for freeing the buffer with g_free() when you - * are done with it. The buffer is freed for you on error. + * are done with it. * * See also: vips_webpsave(). * @@ -2542,7 +2557,12 @@ vips_webpsave_buffer( VipsImage *in, void **buf, size_t *len, ... ) * * Optional arguments: * - * @Q: quality factor + * @Q: %gint quality factor + * @lossless: %gboolean enables lossless compression + * @preset: #VipsForeignWebpPreset choose lossy compression preset + * @smart_subsample: %gboolean enables high quality chroma subsampling + * @near_lossless: %gboolean use preprocessing in lossless mode (controlled by Q) + * @alpha_q: %gint set alpha quality in lossless mode * * As vips_webpsave(), but save as a mime webp on stdout. * diff --git a/libvips/foreign/vips2webp.c b/libvips/foreign/vips2webp.c index 17726218..05301d85 100644 --- a/libvips/foreign/vips2webp.c +++ b/libvips/foreign/vips2webp.c @@ -4,6 +4,8 @@ * - from vips2jpeg.c * 31/5/16 * - buffer write ignored lossless, thanks aaron42net + * 2/5/16 Felix Bünemann + * - used advanced encoding API, expose controls */ /* @@ -99,34 +101,36 @@ init_memory_writer( VipsWebPMemoryWriter *writer ) { static int memory_write( const uint8_t *data, size_t data_size, const WebPPicture *picture ) { - VipsWebPMemoryWriter* const w = (VipsWebPMemoryWriter*) picture->custom_ptr; + VipsWebPMemoryWriter * const writer = + (VipsWebPMemoryWriter*) picture->custom_ptr; + size_t next_size; - if( w == NULL ) + if( !writer ) return( 0 ); - next_size = w->size + data_size; + next_size = writer->size + data_size; - if( next_size > w->max_size ) { + if( next_size > writer->max_size ) { uint8_t *new_mem; const size_t next_max_size = - VIPS_MAX( 8192, VIPS_MAX( next_size, w->max_size * 2 ) ); + VIPS_MAX( 8192, VIPS_MAX( next_size, + writer->max_size * 2 ) ); - new_mem = (uint8_t*) g_try_malloc( next_max_size ); - if( new_mem == NULL ) + if( !(new_mem = (uint8_t*) g_try_malloc( next_max_size )) ) return( 0 ); - if( w->size > 0 ) - memcpy( new_mem, w->mem, w->size ); + if( writer->size > 0 ) + memcpy( new_mem, writer->mem, writer->size ); - g_free( w->mem ); - w->mem = new_mem; - w->max_size = next_max_size; + g_free( writer->mem ); + writer->mem = new_mem; + writer->max_size = next_max_size; } if( data_size > 0 ) { - memcpy( w->mem + w->size, data, data_size ); - w->size += data_size; + memcpy( writer->mem + writer->size, data, data_size ); + writer->size += data_size; } return( 1 ); @@ -142,7 +146,7 @@ write_webp( WebPPicture *pic, VipsImage *in, WebPConfig config; webp_import import; - if ( !WebPConfigPreset(&config, get_preset( preset ), Q) ) { + if ( !WebPConfigPreset( &config, get_preset( preset ), Q ) ) { vips_error( "vips2webp", "%s", _( "config version error" ) ); return( -1 ); @@ -178,7 +182,7 @@ write_webp( WebPPicture *pic, VipsImage *in, "%s", _( "smart_subsample unsupported" ) ); #endif - if( !WebPValidateConfig(&config) ) { + if( !WebPValidateConfig( &config ) ) { vips_error( "vips2webp", "%s", _( "invalid configuration" ) ); return( -1 ); @@ -269,7 +273,6 @@ vips__webp_write_buffer( VipsImage *in, void **obuf, size_t *olen, { WebPPicture pic; VipsWebPMemoryWriter writer; - FILE *fp; if( !WebPPictureInit( &pic ) ) { vips_error( "vips2webp", diff --git a/libvips/include/vips/foreign.h b/libvips/include/vips/foreign.h index a3a9af8e..218b7470 100644 --- a/libvips/include/vips/foreign.h +++ b/libvips/include/vips/foreign.h @@ -341,11 +341,9 @@ int vips_jpegsave_mime( VipsImage *in, ... ) /** * VipsForeignWebpPreset: * @VIPS_FOREIGN_WEBP_PRESET_DEFAULT: default preset - * @VIPS_FOREIGN_WEBP_PRESET_PICTURE: digital picture, like portrait, - * inner shot + * @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_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 * From 1ae92bb15ff5eed7f8aa33f7148e6ba9b7a800ef Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Mon, 2 May 2016 10:12:37 +0100 Subject: [PATCH 12/34] make optional args into bullets make docs easier to read --- libvips/arithmetic/hist_find.c | 2 +- libvips/arithmetic/hist_find_ndim.c | 2 +- libvips/arithmetic/hough_circle.c | 6 +- libvips/arithmetic/hough_line.c | 4 +- libvips/arithmetic/linear.c | 4 +- libvips/arithmetic/max.c | 12 +- libvips/arithmetic/measure.c | 8 +- libvips/arithmetic/min.c | 12 +- libvips/colour/colourspace.c | 2 +- libvips/colour/icc_transform.c | 24 ++-- libvips/colour/scRGB2BW.c | 2 +- libvips/colour/scRGB2sRGB.c | 2 +- libvips/conversion/arrayjoin.c | 14 +- libvips/conversion/autorot.c | 2 +- libvips/conversion/bandfold.c | 2 +- libvips/conversion/bandrank.c | 2 +- libvips/conversion/bandunfold.c | 2 +- libvips/conversion/cache.c | 6 +- libvips/conversion/cast.c | 2 +- libvips/conversion/copy.c | 20 +-- libvips/conversion/embed.c | 4 +- libvips/conversion/extract.c | 2 +- libvips/conversion/flatten.c | 4 +- libvips/conversion/gamma.c | 2 +- libvips/conversion/ifthenelse.c | 2 +- libvips/conversion/insert.c | 4 +- libvips/conversion/join.c | 8 +- libvips/conversion/msb.c | 2 +- libvips/conversion/premultiply.c | 2 +- libvips/conversion/rot45.c | 2 +- libvips/conversion/scale.c | 4 +- libvips/conversion/sequential.c | 6 +- libvips/conversion/subsample.c | 2 +- libvips/conversion/tilecache.c | 18 +-- libvips/conversion/unpremultiply.c | 2 +- libvips/conversion/wrap.c | 4 +- libvips/convolution/conv.c | 6 +- libvips/convolution/convsep.c | 6 +- libvips/convolution/gaussblur.c | 4 +- libvips/convolution/sharpen.c | 12 +- libvips/create/black.c | 2 +- libvips/create/eye.c | 4 +- libvips/create/gaussmat.c | 4 +- libvips/create/gaussnoise.c | 4 +- libvips/create/grey.c | 2 +- libvips/create/identity.c | 6 +- libvips/create/invertlut.c | 2 +- libvips/create/logmat.c | 4 +- libvips/create/mask_butterworth.c | 8 +- libvips/create/mask_butterworth_band.c | 8 +- libvips/create/mask_butterworth_ring.c | 8 +- libvips/create/mask_fractal.c | 8 +- libvips/create/mask_gaussian.c | 8 +- libvips/create/mask_gaussian_band.c | 8 +- libvips/create/mask_gaussian_ring.c | 8 +- libvips/create/mask_ideal.c | 8 +- libvips/create/mask_ideal_band.c | 8 +- libvips/create/mask_ideal_ring.c | 8 +- libvips/create/sines.c | 6 +- libvips/create/text.c | 10 +- libvips/create/tonelut.c | 20 +-- libvips/create/xyz.c | 6 +- libvips/create/zone.c | 2 +- libvips/draw/draw_circle.c | 4 +- libvips/draw/draw_flood.c | 24 ++-- libvips/draw/draw_image.c | 2 +- libvips/draw/draw_rect.c | 4 +- libvips/foreign/csvload.c | 8 +- libvips/foreign/csvsave.c | 2 +- libvips/foreign/dzsave.c | 20 +-- libvips/foreign/foreign.c | 178 ++++++++++++------------- libvips/foreign/ppmsave.c | 4 +- libvips/foreign/rawload.c | 2 +- libvips/freqfilt/invfft.c | 2 +- libvips/histogram/hist_equal.c | 2 +- libvips/histogram/maplut.c | 2 +- libvips/histogram/stdif.c | 8 +- libvips/iofuncs/image.c | 4 +- libvips/iofuncs/system.c | 10 +- libvips/morphology/labelregions.c | 2 +- libvips/mosaicing/global_balance.c | 4 +- libvips/mosaicing/match.c | 8 +- libvips/mosaicing/merge.c | 2 +- libvips/mosaicing/mosaic.c | 8 +- libvips/mosaicing/mosaic1.c | 12 +- libvips/resample/affine.c | 12 +- libvips/resample/mapim.c | 2 +- libvips/resample/quadratic.c | 2 +- libvips/resample/reduce.c | 2 +- libvips/resample/resize.c | 4 +- libvips/resample/similarity.c | 14 +- 91 files changed, 362 insertions(+), 364 deletions(-) diff --git a/libvips/arithmetic/hist_find.c b/libvips/arithmetic/hist_find.c index 465d3452..35227c4a 100644 --- a/libvips/arithmetic/hist_find.c +++ b/libvips/arithmetic/hist_find.c @@ -475,7 +475,7 @@ vips_hist_find_init( VipsHistFind *hist_find ) * * Optional arguments: * - * @band: band to equalise + * * @band: band to equalise * * Find the histogram of @in. Find the histogram for band @band (producing a * one-band histogram), or for all bands (producing an n-band histogram) if diff --git a/libvips/arithmetic/hist_find_ndim.c b/libvips/arithmetic/hist_find_ndim.c index e0d930d8..b0b3ce5f 100644 --- a/libvips/arithmetic/hist_find_ndim.c +++ b/libvips/arithmetic/hist_find_ndim.c @@ -323,7 +323,7 @@ vips_hist_find_ndim_init( VipsHistFindNDim *ndim ) * * Optional arguments: * - * @bins: number of bins to make on each axis + * * @bins: number of bins to make on each axis * * Make a one, two or three dimensional histogram of a 1, 2 or * 3 band image. Divide each axis into @bins bins .. ie. diff --git a/libvips/arithmetic/hough_circle.c b/libvips/arithmetic/hough_circle.c index 620345e1..fd3fd248 100644 --- a/libvips/arithmetic/hough_circle.c +++ b/libvips/arithmetic/hough_circle.c @@ -275,9 +275,9 @@ vips_hough_circle_init( VipsHoughCircle *hough_circle ) * * Optional arguments: * - * @scale: scale down dimensions by this much - * @min_radius: smallest radius to search for - * @max_radius: largest radius to search for + * * @scale: scale down dimensions by this much + * * @min_radius: smallest radius to search for + * * @max_radius: largest radius to search for * * Find the circular Hough transform of an image. @in must be one band, with * non-zero pixels for image edges. @out is three-band, with the third channel diff --git a/libvips/arithmetic/hough_line.c b/libvips/arithmetic/hough_line.c index eaa5b8bd..e32e4be4 100644 --- a/libvips/arithmetic/hough_line.c +++ b/libvips/arithmetic/hough_line.c @@ -169,8 +169,8 @@ vips_hough_line_init( VipsHoughLine *hough_line ) * * Optional arguments: * - * @width: horizontal size of parameter space - * @height: vertical size of parameter space + * * @width: horizontal size of parameter space + * * @height: vertical size of parameter space * * Find the line Hough transform for @in. @in must have one band. @out has one * band, with pixels being the number of votes for that line. The X dimension diff --git a/libvips/arithmetic/linear.c b/libvips/arithmetic/linear.c index 9aba5054..cad7751d 100644 --- a/libvips/arithmetic/linear.c +++ b/libvips/arithmetic/linear.c @@ -448,7 +448,7 @@ vips_linearv( VipsImage *in, VipsImage **out, * * Optional arguments: * - * @uchar: output uchar pixels + * * @uchar: output uchar pixels * * Pass an image through a linear transform, ie. (@out = @in * @a + @b). Output * is float for integer input, double for double input, complex for @@ -489,7 +489,7 @@ vips_linear( VipsImage *in, VipsImage **out, double *a, double *b, int n, ... ) * * Optional arguments: * - * @uchar: output uchar pixels + * * @uchar: output uchar pixels * * Run vips_linear() with a single constant. * diff --git a/libvips/arithmetic/max.c b/libvips/arithmetic/max.c index f5fefc1b..14ba6e0f 100644 --- a/libvips/arithmetic/max.c +++ b/libvips/arithmetic/max.c @@ -486,12 +486,12 @@ vips_max_init( VipsMax *max ) * * Optional arguments: * - * @x: horizontal position of maximum - * @y: vertical position of maximum - * @size: number of maxima to find - * @out_array: return array of maximum values - * @x_array: corresponding horizontal positions - * @y_array: corresponding vertical positions + * * @x: horizontal position of maximum + * * @y: vertical position of maximum + * * @size: number of maxima to find + * * @out_array: return array of maximum values + * * @x_array: corresponding horizontal positions + * * @y_array: corresponding vertical positions * * This operation finds the maximum value in an image. * diff --git a/libvips/arithmetic/measure.c b/libvips/arithmetic/measure.c index 67d6feb6..9e7c881e 100644 --- a/libvips/arithmetic/measure.c +++ b/libvips/arithmetic/measure.c @@ -269,10 +269,10 @@ vips_measure_init( VipsMeasure *measure ) * * Optional arguments: * - * @left: area of image containing chart - * @top: area of image containing chart - * @width: area of image containing chart - * @height: area of image containing chart + * * @left: area of image containing chart + * * @top: area of image containing chart + * * @width: area of image containing chart + * * @height: area of image containing chart * * Analyse a grid of colour patches, producing an array of patch averages. * The mask has a row for each measured patch and a column for each image diff --git a/libvips/arithmetic/min.c b/libvips/arithmetic/min.c index 0c58145e..f2c24e55 100644 --- a/libvips/arithmetic/min.c +++ b/libvips/arithmetic/min.c @@ -489,12 +489,12 @@ vips_min_init( VipsMin *min ) * * Optional arguments: * - * @x: horizontal position of minimum - * @y: vertical position of minimum - * @size: number of minima to find - * @out_array: return array of minimum values - * @x_array: corresponding horizontal positions - * @y_array: corresponding vertical positions + * * @x: horizontal position of minimum + * * @y: vertical position of minimum + * * @size: number of minima to find + * * @out_array: return array of minimum values + * * @x_array: corresponding horizontal positions + * * @y_array: corresponding vertical positions * * This operation finds the minimum value in an image. * diff --git a/libvips/colour/colourspace.c b/libvips/colour/colourspace.c index 298ecc2e..1221c3c2 100644 --- a/libvips/colour/colourspace.c +++ b/libvips/colour/colourspace.c @@ -625,7 +625,7 @@ vips_colourspace_init( VipsColourspace *colourspace ) * * Optional arguments: * - * @source_space: input colour space + * * @source_space: input colour space * * This operation looks at the interpretation field of @in (or uses * @source_space, if set) and runs diff --git a/libvips/colour/icc_transform.c b/libvips/colour/icc_transform.c index b9fbdab7..92c29785 100644 --- a/libvips/colour/icc_transform.c +++ b/libvips/colour/icc_transform.c @@ -1255,10 +1255,10 @@ vips_icc_ac2rc( VipsImage *in, VipsImage **out, const char *profile_filename ) * * Optional arguments: * - * @input_profile: get the input profile from here - * @intent: transform with this intent - * @embedded: use profile embedded in input image - * @pcs: use XYZ or LAB PCS + * * @input_profile: get the input profile from here + * * @intent: transform with this intent + * * @embedded: use profile embedded in input image + * * @pcs: use XYZ or LAB PCS * * Import an image from device space to D65 LAB with an ICC profile. If @pcs is * set to #VIPS_PCS_XYZ, use CIE XYZ PCS instead. @@ -1294,10 +1294,10 @@ vips_icc_import( VipsImage *in, VipsImage **out, ... ) * * Optional arguments: * - * @intent: transform with this intent - * @depth: depth of output image in bits - * @output_profile: get the output profile from here - * @pcs: use XYZ or LAB PCS + * * @intent: transform with this intent + * * @depth: depth of output image in bits + * * @output_profile: get the output profile from here + * * @pcs: use XYZ or LAB PCS * * Export an image from D65 LAB to device space with an ICC profile. * If @pcs is @@ -1330,10 +1330,10 @@ vips_icc_export( VipsImage *in, VipsImage **out, ... ) * * Optional arguments: * - * @input_profile: get the input profile from here - * @intent: transform with this intent - * @depth: depth of output image in bits - * @embedded: use profile embedded in input image + * * @input_profile: get the input profile from here + * * @intent: transform with this intent + * * @depth: depth of output image in bits + * * @embedded: use profile embedded in input image * * Transform an image with a pair of ICC profiles. The input image is moved to * profile-connection space with the input profile and then to the output diff --git a/libvips/colour/scRGB2BW.c b/libvips/colour/scRGB2BW.c index 3d5803a7..19ee0411 100644 --- a/libvips/colour/scRGB2BW.c +++ b/libvips/colour/scRGB2BW.c @@ -268,7 +268,7 @@ vips_scRGB2BW_init( VipsscRGB2BW *scRGB2BW ) * * Optional arguments: * - * @depth: depth of output image in bits + * * @depth: depth of output image in bits * * Convert an scRGB image to greyscale. Set @depth to 16 to get 16-bit output. * diff --git a/libvips/colour/scRGB2sRGB.c b/libvips/colour/scRGB2sRGB.c index 6e3f2a78..83702485 100644 --- a/libvips/colour/scRGB2sRGB.c +++ b/libvips/colour/scRGB2sRGB.c @@ -296,7 +296,7 @@ vips_scRGB2sRGB_init( VipsscRGB2sRGB *scRGB2sRGB ) * * Optional arguments: * - * @depth: depth of output image in bits + * * @depth: depth of output image in bits * * Convert an scRGB image to sRGB. Set @depth to 16 to get 16-bit output. * diff --git a/libvips/conversion/arrayjoin.c b/libvips/conversion/arrayjoin.c index 712791c2..227c28b4 100644 --- a/libvips/conversion/arrayjoin.c +++ b/libvips/conversion/arrayjoin.c @@ -397,13 +397,13 @@ vips_arrayjoinv( VipsImage **in, VipsImage **out, int n, va_list ap ) * * Optional arguments: * - * @across: number of images per row - * @shim: space between images, in pixels - * @background: background ink colour - * @halign: low, centre or high alignment - * @valign: low, centre or high alignment - * @hspacing: horizontal distance between images - * @vspacing: vertical distance between images + * * @across: number of images per row + * * @shim: space between images, in pixels + * * @background: background ink colour + * * @halign: low, centre or high alignment + * * @valign: low, centre or high alignment + * * @hspacing: horizontal distance between images + * * @vspacing: vertical distance between images * * Lay out the images in @in in a grid. The grid is @across images across and * however high is necessary to use up all of @in. Images are set down diff --git a/libvips/conversion/autorot.c b/libvips/conversion/autorot.c index 17ccb120..f25994ee 100644 --- a/libvips/conversion/autorot.c +++ b/libvips/conversion/autorot.c @@ -214,7 +214,7 @@ vips_autorot_init( VipsAutorot *autorot ) * * Optional arguments: * - * @angle: output #VipsAngle the image was rotated by + * * @angle: output #VipsAngle the image was rotated by * * Look at the exif tags and rotate the image to make it upright. The * orientation tag is removed from @out to prevent accidental double rotation. diff --git a/libvips/conversion/bandfold.c b/libvips/conversion/bandfold.c index 81635784..b5a1d309 100644 --- a/libvips/conversion/bandfold.c +++ b/libvips/conversion/bandfold.c @@ -186,7 +186,7 @@ vips_bandfold_init( VipsBandfold *bandfold ) * * Optional arguments: * - * @factor: fold by this factor + * * @factor: fold by this factor * * Fold up an image horizontally: width is collapsed into bands. * Use @factor to set how much to fold by: @factor 3, for example, will make diff --git a/libvips/conversion/bandrank.c b/libvips/conversion/bandrank.c index 8f25f501..06ceb969 100644 --- a/libvips/conversion/bandrank.c +++ b/libvips/conversion/bandrank.c @@ -286,7 +286,7 @@ vips_bandrankv( VipsImage **in, VipsImage **out, int n, va_list ap ) * * Optional arguments: * - * @index: pick this index from list of sorted values + * * @index: pick this index from list of sorted values * * Sorts the images @in band-element-wise, then outputs an * image in which each band element is selected from the sorted list by the diff --git a/libvips/conversion/bandunfold.c b/libvips/conversion/bandunfold.c index ebfb5d53..c0491031 100644 --- a/libvips/conversion/bandunfold.c +++ b/libvips/conversion/bandunfold.c @@ -189,7 +189,7 @@ vips_bandunfold_init( VipsBandunfold *bandunfold ) * * Optional arguments: * - * @factor: unfold by this factor + * * @factor: unfold by this factor * * Unfold image bands into x axis. * Use @factor to set how much to unfold by: @factor 3, for example, will make diff --git a/libvips/conversion/cache.c b/libvips/conversion/cache.c index 52f31790..a7243030 100644 --- a/libvips/conversion/cache.c +++ b/libvips/conversion/cache.c @@ -144,9 +144,9 @@ vips_cache_init( VipsCache *cache ) * * Optional arguments: * - * @tile_width: width of tiles in cache - * @tile_height: height of tiles in cache - * @max_tiles: maximum number of tiles to cache + * * @tile_width: width of tiles in cache + * * @tile_height: height of tiles in cache + * * @max_tiles: maximum number of tiles to cache * * This operation behaves rather like vips_copy() between images * @in and @out, except that it keeps a cache of computed pixels. diff --git a/libvips/conversion/cast.c b/libvips/conversion/cast.c index 4650f1db..f9197478 100644 --- a/libvips/conversion/cast.c +++ b/libvips/conversion/cast.c @@ -587,7 +587,7 @@ vips_castv( VipsImage *in, VipsImage **out, VipsBandFormat format, va_list ap ) * * Optional arguments: * - * @shift: integer values are shifted + * * @shift: integer values are shifted * * Convert @in to @format. You can convert between any pair of formats. * Floats are truncated (not rounded). Out of range values are clipped. diff --git a/libvips/conversion/copy.c b/libvips/conversion/copy.c index b02359bc..eecf9ef5 100644 --- a/libvips/conversion/copy.c +++ b/libvips/conversion/copy.c @@ -366,16 +366,16 @@ vips_copy_init( VipsCopy *copy ) * * Optional arguments: * - * @width: set image width - * @height: set image height - * @bands: set image bands - * @format: set image format - * @coding: set image coding - * @interpretation: set image interpretation - * @xres: set image xres - * @yres: set image yres - * @xoffset: set image xoffset - * @yoffset: set image yoffset + * * @width: set image width + * * @height: set image height + * * @bands: set image bands + * * @format: set image format + * * @coding: set image coding + * * @interpretation: set image interpretation + * * @xres: set image xres + * * @yres: set image yres + * * @xoffset: set image xoffset + * * @yoffset: set image yoffset * * Copy an image, optionally modifying the header. VIPS copies images by * copying pointers, so this operation is instant, even for very large images. diff --git a/libvips/conversion/embed.c b/libvips/conversion/embed.c index 9e77dc85..14c1071d 100644 --- a/libvips/conversion/embed.c +++ b/libvips/conversion/embed.c @@ -627,8 +627,8 @@ vips_embed_init( VipsEmbed *embed ) * * Optional arguments: * - * @extend: #VipsExtend to generate the edge pixels (default: black) - * @background: #VipsArrayDouble colour for edge pixels + * * @extend: #VipsExtend to generate the edge pixels (default: black) + * * @background: #VipsArrayDouble colour for edge pixels * * The opposite of vips_extract_area(): embed @in within an image of size * @width by @height at position @x, @y. diff --git a/libvips/conversion/extract.c b/libvips/conversion/extract.c index 052ea5f5..879efae1 100644 --- a/libvips/conversion/extract.c +++ b/libvips/conversion/extract.c @@ -455,7 +455,7 @@ vips_extract_band_init( VipsExtractBand *extract ) * * Optional arguments: * - * @n: number of bands to extract + * * @n: number of bands to extract * * Extract a band or bands from an image. Extracting out of range is an error. * diff --git a/libvips/conversion/flatten.c b/libvips/conversion/flatten.c index b95e0237..486515d3 100644 --- a/libvips/conversion/flatten.c +++ b/libvips/conversion/flatten.c @@ -409,8 +409,8 @@ vips_flatten_init( VipsFlatten *flatten ) * * Optional arguments: * - * @background: #VipsArrayDouble colour for new pixels - * @max_alpha: %gdouble, maximum value for alpha + * * @background: #VipsArrayDouble colour for new pixels + * * @max_alpha: %gdouble, maximum value for alpha * * Take the last band of @in as an alpha and use it to blend the * remaining channels with @background. diff --git a/libvips/conversion/gamma.c b/libvips/conversion/gamma.c index 4fe6549f..91fe63af 100644 --- a/libvips/conversion/gamma.c +++ b/libvips/conversion/gamma.c @@ -168,7 +168,7 @@ vips_gamma_init( VipsGamma *gamma ) * * Optional arguments: * - * @exponent: gamma, default 1.0 / 2.4 + * * @exponent: gamma, default 1.0 / 2.4 * * Calculate @in ** (1 / @exponent), normalising to the maximum range of the * input type. For float types use 1.0 as the maximum. diff --git a/libvips/conversion/ifthenelse.c b/libvips/conversion/ifthenelse.c index 4b056b2c..eb5bb2b7 100644 --- a/libvips/conversion/ifthenelse.c +++ b/libvips/conversion/ifthenelse.c @@ -517,7 +517,7 @@ vips_ifthenelse_init( VipsIfthenelse *ifthenelse ) * * Optional arguments: * - * @blend: blend smoothly between @in1 and @in2 + * * @blend: blend smoothly between @in1 and @in2 * * This operation scans the condition image @cond * and uses it to select pixels from either the then image @in1 or the else diff --git a/libvips/conversion/insert.c b/libvips/conversion/insert.c index f37dbd68..872c71d4 100644 --- a/libvips/conversion/insert.c +++ b/libvips/conversion/insert.c @@ -573,8 +573,8 @@ vips_insert_init( VipsInsert *insert ) * * Optional arguments: * - * @expand: expand output to hold whole of both images - * @background: colour for new pixels + * * @expand: expand output to hold whole of both images + * * @background: colour for new pixels * * Insert @sub into @main at position @x, @y. * diff --git a/libvips/conversion/join.c b/libvips/conversion/join.c index 8229fbca..7c2ccc57 100644 --- a/libvips/conversion/join.c +++ b/libvips/conversion/join.c @@ -296,10 +296,10 @@ vips_join_init( VipsJoin *join ) * * Optional arguments: * - * @expand: %TRUE to expand the output image to hold all of the input pixels - * @shim: space between images, in pixels - * @background: background ink colour - * @align: low, centre or high alignment + * * @expand: %TRUE to expand the output image to hold all of the input pixels + * * @shim: space between images, in pixels + * * @background: background ink colour + * * @align: low, centre or high alignment * * Join @in1 and @in2 together, left-right or up-down depending on the value * of @direction. diff --git a/libvips/conversion/msb.c b/libvips/conversion/msb.c index 33f931c8..9aeae360 100644 --- a/libvips/conversion/msb.c +++ b/libvips/conversion/msb.c @@ -269,7 +269,7 @@ vips_msb_init( VipsMsb *msb ) * * Optional arguments: * - * @band: msb just this band + * * @band: msb just this band * * Turn any integer image to 8-bit unsigned char by discarding all but the most * significant byte. Signed values are converted to unsigned by adding 128. diff --git a/libvips/conversion/premultiply.c b/libvips/conversion/premultiply.c index 4d842de3..7923100e 100644 --- a/libvips/conversion/premultiply.c +++ b/libvips/conversion/premultiply.c @@ -273,7 +273,7 @@ vips_premultiply_init( VipsPremultiply *premultiply ) * * Optional arguments: * - * @max_alpha: %gdouble, maximum value for alpha + * * @max_alpha: %gdouble, maximum value for alpha * * Premultiplies any alpha channel. * The final band is taken to be the alpha diff --git a/libvips/conversion/rot45.c b/libvips/conversion/rot45.c index c049a5aa..dc0b1be7 100644 --- a/libvips/conversion/rot45.c +++ b/libvips/conversion/rot45.c @@ -291,7 +291,7 @@ vips_rot45_init( VipsRot45 *rot45 ) * * Optional arguments: * - * @angle: rotation angle + * * @angle: rotation angle * * Rotate @in by a multiple of 45 degrees. Odd-length sides and square images * only. diff --git a/libvips/conversion/scale.c b/libvips/conversion/scale.c index af9980a9..492e80a7 100644 --- a/libvips/conversion/scale.c +++ b/libvips/conversion/scale.c @@ -183,8 +183,8 @@ vips_scale_init( VipsScale *scale ) * * Optional arguments: * - * @log: log scale pixels - * @exp: exponent for log scale + * * @log: log scale pixels + * * @exp: exponent for log scale * * Search the image for the maximum and minimum value, then return the image * as unsigned 8-bit, scaled so that the maximum value is 255 and the diff --git a/libvips/conversion/sequential.c b/libvips/conversion/sequential.c index 5db03b3a..c6a6bbfc 100644 --- a/libvips/conversion/sequential.c +++ b/libvips/conversion/sequential.c @@ -364,9 +364,9 @@ vips_sequential_init( VipsSequential *sequential ) * * Optional arguments: * - * @trace: trace requests - * @strip_height: height of cache strips - * @access: access pattern + * * @trace: trace requests + * * @strip_height: height of cache strips + * * @access: access pattern * * This operation behaves rather like vips_copy() between images * @in and @out, except that it checks that pixels are only requested diff --git a/libvips/conversion/subsample.c b/libvips/conversion/subsample.c index bcf1234c..0f5029ac 100644 --- a/libvips/conversion/subsample.c +++ b/libvips/conversion/subsample.c @@ -314,7 +314,7 @@ vips_subsample_init( VipsSubsample *subsample ) * * Optional arguments: * - * @point: turn on point sample mode + * * @point: turn on point sample mode * * Subsample an image by an integer fraction. This is fast, nearest-neighbour * shrink. diff --git a/libvips/conversion/tilecache.c b/libvips/conversion/tilecache.c index c6c6702d..75873485 100644 --- a/libvips/conversion/tilecache.c +++ b/libvips/conversion/tilecache.c @@ -824,12 +824,12 @@ vips_tile_cache_init( VipsTileCache *cache ) * * Optional arguments: * - * @tile_width: width of tiles in cache - * @tile_height: height of tiles in cache - * @max_tiles: maximum number of tiles to cache - * @access: hint expected access pattern #VipsAccess - * @threaded: allow many threads - * @persistent: don't drop cache at end of computation + * * @tile_width: width of tiles in cache + * * @tile_height: height of tiles in cache + * * @max_tiles: maximum number of tiles to cache + * * @access: hint expected access pattern #VipsAccess + * * @threaded: allow many threads + * * @persistent: don't drop cache at end of computation * * This operation behaves rather like vips_copy() between images * @in and @out, except that it keeps a cache of computed pixels. @@ -1018,9 +1018,9 @@ vips_line_cache_init( VipsLineCache *cache ) * * Optional arguments: * - * @access: hint expected access pattern #VipsAccess - * @tile_height: height of tiles in cache - * @threaded: allow many threads + * * @access: hint expected access pattern #VipsAccess + * * @tile_height: height of tiles in cache + * * @threaded: allow many threads * * This operation behaves rather like vips_copy() between images * @in and @out, except that it keeps a cache of computed scanlines. diff --git a/libvips/conversion/unpremultiply.c b/libvips/conversion/unpremultiply.c index 6105d1e5..39f1f86e 100644 --- a/libvips/conversion/unpremultiply.c +++ b/libvips/conversion/unpremultiply.c @@ -283,7 +283,7 @@ vips_unpremultiply_init( VipsUnpremultiply *unpremultiply ) * * Optional arguments: * - * @max_alpha: %gdouble, maximum value for alpha + * * @max_alpha: %gdouble, maximum value for alpha * * Unpremultiplies any alpha channel. * The final band is taken to be the alpha diff --git a/libvips/conversion/wrap.c b/libvips/conversion/wrap.c index 7c02f208..e97ef491 100644 --- a/libvips/conversion/wrap.c +++ b/libvips/conversion/wrap.c @@ -150,8 +150,8 @@ vips_wrap_init( VipsWrap *wrap ) * * Optional arguments: * - * @x: horizontal displacement - * @y: vertical displacement + * * @x: horizontal displacement + * * @y: vertical displacement * * Slice an image up and move the segments about so that the pixel that was * at 0, 0 is now at @x, @y. If @x and @y are not set, they default to the diff --git a/libvips/convolution/conv.c b/libvips/convolution/conv.c index 234e275c..ff7dfd51 100644 --- a/libvips/convolution/conv.c +++ b/libvips/convolution/conv.c @@ -175,9 +175,9 @@ vips_conv_init( VipsConv *conv ) * * Optional arguments: * - * @precision: calculation accuracy - * @layers: number of layers for approximation - * @cluster: cluster lines closer than this distance + * * @precision: calculation accuracy + * * @layers: number of layers for approximation + * * @cluster: cluster lines closer than this distance * * Convolution. * diff --git a/libvips/convolution/convsep.c b/libvips/convolution/convsep.c index dc3ceea2..7838ec41 100644 --- a/libvips/convolution/convsep.c +++ b/libvips/convolution/convsep.c @@ -143,9 +143,9 @@ vips_convsep_init( VipsConvsep *convsep ) * * Optional arguments: * - * @precision: calculation accuracy - * @layers: number of layers for approximation - * @cluster: cluster lines closer than this distance + * * @precision: calculation accuracy + * * @layers: number of layers for approximation + * * @cluster: cluster lines closer than this distance * * Perform a separable convolution of @in with @mask. * See vips_conv() for a detailed description. diff --git a/libvips/convolution/gaussblur.c b/libvips/convolution/gaussblur.c index ccb8c1d9..41800097 100644 --- a/libvips/convolution/gaussblur.c +++ b/libvips/convolution/gaussblur.c @@ -168,8 +168,8 @@ vips_gaussblur_init( VipsGaussblur *gaussblur ) * * Optional arguments: * - * @precision: #VipsPrecision for blur, default VIPS_PRECISION_INTEGER - * @min_ampl: minimum amplitude, default 0.2 + * * @precision: #VipsPrecision for blur, default VIPS_PRECISION_INTEGER + * * @min_ampl: minimum amplitude, default 0.2 * * This operator runs vips_gaussmat() and vips_convsep() for you on an image. * Set @min_ampl smaller to generate a larger, more accurate mask. Set @sigma diff --git a/libvips/convolution/sharpen.c b/libvips/convolution/sharpen.c index 05e6abff..6a260fbe 100644 --- a/libvips/convolution/sharpen.c +++ b/libvips/convolution/sharpen.c @@ -394,12 +394,12 @@ vips_sharpen_init( VipsSharpen *sharpen ) * * Optional arguments: * - * @sigma: sigma of gaussian - * @x1: flat/jaggy threshold - * @y2: maximum amount of brightening - * @y3: maximum amount of darkening - * @m1: slope for flat areas - * @m2: slope for jaggy areas + * * @sigma: sigma of gaussian + * * @x1: flat/jaggy threshold + * * @y2: maximum amount of brightening + * * @y3: maximum amount of darkening + * * @m1: slope for flat areas + * * @m2: slope for jaggy areas * * Selectively sharpen the L channel of a LAB image. The input image is * transformed to #VIPS_INTERPRETATION_LABS. diff --git a/libvips/create/black.c b/libvips/create/black.c index dfa2ede2..65b567ac 100644 --- a/libvips/create/black.c +++ b/libvips/create/black.c @@ -162,7 +162,7 @@ vips_black_init( VipsBlack *black ) * * Optional arguments: * - * @bands: output bands + * * @bands: output bands * * Make a black unsigned char image of a specified size. * diff --git a/libvips/create/eye.c b/libvips/create/eye.c index c429b68e..edac0d3a 100644 --- a/libvips/create/eye.c +++ b/libvips/create/eye.c @@ -123,8 +123,8 @@ vips_eye_init( VipsEye *eye ) * * Optional arguments: * - * @factor: maximum spatial frequency - * @uchar: output a uchar image + * * @factor: maximum spatial frequency + * * @uchar: output a uchar image * * Create a test pattern with increasing spatial frequence in X and * amplitude in Y. @factor should be between 0 and 1 and determines the diff --git a/libvips/create/gaussmat.c b/libvips/create/gaussmat.c index 93623d12..ba41013b 100644 --- a/libvips/create/gaussmat.c +++ b/libvips/create/gaussmat.c @@ -234,8 +234,8 @@ vips_gaussmat_init( VipsGaussmat *gaussmat ) * * Optional arguments: * - * @separable: generate a separable gaussian - * @precision: #VipsPrecision for @out + * * @separable: generate a separable gaussian + * * @precision: #VipsPrecision for @out * * Creates a circularly symmetric Gaussian image of radius * @sigma. The size of the mask is determined by the variable @min_ampl; diff --git a/libvips/create/gaussnoise.c b/libvips/create/gaussnoise.c index 5fee656e..1530905e 100644 --- a/libvips/create/gaussnoise.c +++ b/libvips/create/gaussnoise.c @@ -195,8 +195,8 @@ vips_gaussnoise_init( VipsGaussnoise *gaussnoise ) * * Optional arguments: * - * @mean: mean of generated pixels - * @sigma: standard deviation of generated pixels + * * @mean: mean of generated pixels + * * @sigma: standard deviation of generated pixels * * Make a one band float image of gaussian noise with the specified * distribution. The noise distribution is created by averaging 12 random diff --git a/libvips/create/grey.c b/libvips/create/grey.c index 2c602833..1ec5c58c 100644 --- a/libvips/create/grey.c +++ b/libvips/create/grey.c @@ -107,7 +107,7 @@ vips_grey_init( VipsGrey *grey ) * * Optional arguments: * - * @uchar: output a uchar image + * * @uchar: output a uchar image * * Create a one-band float image with the left-most column zero and the * right-most 1. Intermediate pixels are a linear ramp. diff --git a/libvips/create/identity.c b/libvips/create/identity.c index d596bd12..90241667 100644 --- a/libvips/create/identity.c +++ b/libvips/create/identity.c @@ -178,9 +178,9 @@ vips_identity_init( VipsIdentity *identity ) * * Optional arguments: * - * @bands: number of bands to create - * @ushort: %TRUE for an unsigned short identity - * @size: number of LUT elements for a ushort image + * * @bands: number of bands to create + * * @ushort: %TRUE for an unsigned short identity + * * @size: number of LUT elements for a ushort image * * Creates an identity lookup table, ie. one which will leave an image * unchanged when applied with vips_maplut(). Each entry in the table has a diff --git a/libvips/create/invertlut.c b/libvips/create/invertlut.c index e9c9b2b0..d2e99795 100644 --- a/libvips/create/invertlut.c +++ b/libvips/create/invertlut.c @@ -314,7 +314,7 @@ vips_invertlut_init( VipsInvertlut *lut ) * * Optional arguments: * - * @size: generate this much + * * @size: generate this much * * Given a mask of target values and real values, generate a LUT which * will map reals to targets. Handy for linearising images from diff --git a/libvips/create/logmat.c b/libvips/create/logmat.c index 64520504..db4384eb 100644 --- a/libvips/create/logmat.c +++ b/libvips/create/logmat.c @@ -251,8 +251,8 @@ vips_logmat_init( VipsLogmat *logmat ) * * Optional arguments: * - * @separable: generate a separable mask - * @precision: #VipsPrecision for @out + * * @separable: generate a separable mask + * * @precision: #VipsPrecision for @out * * Creates a circularly symmetric Laplacian of Gaussian mask * of radius diff --git a/libvips/create/mask_butterworth.c b/libvips/create/mask_butterworth.c index 3e6c7f0a..35a75316 100644 --- a/libvips/create/mask_butterworth.c +++ b/libvips/create/mask_butterworth.c @@ -127,10 +127,10 @@ vips_mask_butterworth_init( VipsMaskButterworth *butterworth ) * * Optional arguments: * - * @nodc: don't set the DC pixel - * @reject: invert the filter sense - * @optical: coordinates in optical space - * @uchar: output a uchar image + * * @nodc: don't set the DC pixel + * * @reject: invert the filter sense + * * @optical: coordinates in optical space + * * @uchar: output a uchar image * * Make an butterworth high- or low-pass filter, that is, one with a variable, * smooth transition diff --git a/libvips/create/mask_butterworth_band.c b/libvips/create/mask_butterworth_band.c index e29347d9..dd3e8865 100644 --- a/libvips/create/mask_butterworth_band.c +++ b/libvips/create/mask_butterworth_band.c @@ -171,10 +171,10 @@ vips_mask_butterworth_band_init( * * Optional arguments: * - * @nodc: don't set the DC pixel - * @reject: invert the filter sense - * @optical: coordinates in optical space - * @uchar: output a uchar image + * * @nodc: don't set the DC pixel + * * @reject: invert the filter sense + * * @optical: coordinates in optical space + * * @uchar: output a uchar image * * Make an butterworth band-pass or band-reject filter, that is, one with a * variable, smooth transition positioned at @frequency_cutoff_x, diff --git a/libvips/create/mask_butterworth_ring.c b/libvips/create/mask_butterworth_ring.c index cd3e7ec9..b5b252de 100644 --- a/libvips/create/mask_butterworth_ring.c +++ b/libvips/create/mask_butterworth_ring.c @@ -131,10 +131,10 @@ vips_mask_butterworth_ring_init( * * Optional arguments: * - * @nodc: don't set the DC pixel - * @reject: invert the filter sense - * @optical: coordinates in optical space - * @uchar: output a uchar image + * * @nodc: don't set the DC pixel + * * @reject: invert the filter sense + * * @optical: coordinates in optical space + * * @uchar: output a uchar image * * Make a butterworth ring-pass or ring-reject filter, that is, one with a * variable, diff --git a/libvips/create/mask_fractal.c b/libvips/create/mask_fractal.c index 48b08b96..9031a415 100644 --- a/libvips/create/mask_fractal.c +++ b/libvips/create/mask_fractal.c @@ -114,10 +114,10 @@ vips_mask_fractal_init( VipsMaskFractal *fractal ) * * Optional arguments: * - * @nodc: don't set the DC pixel - * @reject: invert the filter sense - * @optical: coordinates in optical space - * @uchar: output a uchar image + * * @nodc: don't set the DC pixel + * * @reject: invert the filter sense + * * @optical: coordinates in optical space + * * @uchar: output a uchar image * * This operation should be used to create fractal images by filtering the * power spectrum of Gaussian white noise. See vips_gaussnoise(). diff --git a/libvips/create/mask_gaussian.c b/libvips/create/mask_gaussian.c index d59f5fc8..6dcf7372 100644 --- a/libvips/create/mask_gaussian.c +++ b/libvips/create/mask_gaussian.c @@ -116,10 +116,10 @@ vips_mask_gaussian_init( VipsMaskGaussian *gaussian ) * * Optional arguments: * - * @nodc: don't set the DC pixel - * @reject: invert the filter sense - * @optical: coordinates in optical space - * @uchar: output a uchar image + * * @nodc: don't set the DC pixel + * * @reject: invert the filter sense + * * @optical: coordinates in optical space + * * @uchar: output a uchar image * * Make a gaussian high- or low-pass filter, that is, one with a variable, * smooth transition positioned at @frequency_cutoff. diff --git a/libvips/create/mask_gaussian_band.c b/libvips/create/mask_gaussian_band.c index 22dda78c..7218affd 100644 --- a/libvips/create/mask_gaussian_band.c +++ b/libvips/create/mask_gaussian_band.c @@ -155,10 +155,10 @@ vips_mask_gaussian_band_init( VipsMaskGaussianBand *gaussian_band ) * * Optional arguments: * - * @nodc: don't set the DC pixel - * @reject: invert the filter sense - * @optical: coordinates in optical space - * @uchar: output a uchar image + * * @nodc: don't set the DC pixel + * * @reject: invert the filter sense + * * @optical: coordinates in optical space + * * @uchar: output a uchar image * * Make a gaussian band-pass or band-reject filter, that is, one with a * variable, smooth transition positioned at @frequency_cutoff_x, diff --git a/libvips/create/mask_gaussian_ring.c b/libvips/create/mask_gaussian_ring.c index c99a0b18..8afcf5d2 100644 --- a/libvips/create/mask_gaussian_ring.c +++ b/libvips/create/mask_gaussian_ring.c @@ -124,10 +124,10 @@ vips_mask_gaussian_ring_init( VipsMaskGaussianRing *gaussian_ring ) * * Optional arguments: * - * @nodc: don't set the DC pixel - * @reject: invert the filter sense - * @optical: coordinates in optical space - * @uchar: output a uchar image + * * @nodc: don't set the DC pixel + * * @reject: invert the filter sense + * * @optical: coordinates in optical space + * * @uchar: output a uchar image * * Make a gaussian ring-pass or ring-reject filter, that is, one with a * variable, smooth transition positioned at @frequency_cutoff of width diff --git a/libvips/create/mask_ideal.c b/libvips/create/mask_ideal.c index d8c5fc92..cce19192 100644 --- a/libvips/create/mask_ideal.c +++ b/libvips/create/mask_ideal.c @@ -105,10 +105,10 @@ vips_mask_ideal_init( VipsMaskIdeal *ideal ) * * Optional arguments: * - * @nodc: don't set the DC pixel - * @reject: invert the filter sense - * @optical: coordinates in optical space - * @uchar: output a uchar image + * * @nodc: don't set the DC pixel + * * @reject: invert the filter sense + * * @optical: coordinates in optical space + * * @uchar: output a uchar image * * Make an ideal high- or low-pass filter, that is, one with a sharp cutoff * positioned at @frequency_cutoff, where @frequency_cutoff is in diff --git a/libvips/create/mask_ideal_band.c b/libvips/create/mask_ideal_band.c index 365712f0..6675b44e 100644 --- a/libvips/create/mask_ideal_band.c +++ b/libvips/create/mask_ideal_band.c @@ -137,10 +137,10 @@ vips_mask_ideal_band_init( VipsMaskIdealBand *ideal_band ) * * Optional arguments: * - * @nodc: don't set the DC pixel - * @reject: invert the filter sense - * @optical: coordinates in optical space - * @uchar: output a uchar image + * * @nodc: don't set the DC pixel + * * @reject: invert the filter sense + * * @optical: coordinates in optical space + * * @uchar: output a uchar image * * Make an ideal band-pass or band-reject filter, that is, one with a * sharp cutoff around the point @frequency_cutoff_x, @frequency_cutoff_y, diff --git a/libvips/create/mask_ideal_ring.c b/libvips/create/mask_ideal_ring.c index 32e5b4ee..20e3831b 100644 --- a/libvips/create/mask_ideal_ring.c +++ b/libvips/create/mask_ideal_ring.c @@ -120,10 +120,10 @@ vips_mask_ideal_ring_init( VipsMaskIdealRing *ideal_ring ) * * Optional arguments: * - * @nodc: don't set the DC pixel - * @reject: invert the filter sense - * @optical: coordinates in optical space - * @uchar: output a uchar image + * * @nodc: don't set the DC pixel + * * @reject: invert the filter sense + * * @optical: coordinates in optical space + * * @uchar: output a uchar image * * Make an ideal ring-pass or ring-reject filter, that is, one with a sharp * ring positioned at @frequency_cutoff of width @width, where diff --git a/libvips/create/sines.c b/libvips/create/sines.c index 5511b984..8a60cfb8 100644 --- a/libvips/create/sines.c +++ b/libvips/create/sines.c @@ -154,9 +154,9 @@ vips_sines_init( VipsSines *sines ) * * Optional arguments: * - * @hfreq: horizontal frequency - * @vreq: vertical frequency - * @uchar: output a uchar image + * * @hfreq: horizontal frequency + * * @vreq: vertical frequency + * * @uchar: output a uchar image * * Creates a float one band image of the a sine waveform in two * dimensions. diff --git a/libvips/create/text.c b/libvips/create/text.c index 4ca4e000..90344c6c 100644 --- a/libvips/create/text.c +++ b/libvips/create/text.c @@ -341,11 +341,11 @@ vips_text_init( VipsText *text ) * * Optional arguments: * - * @font: font to render with - * @width: render within this many pixels across - * @alignment: left/centre/right alignment - * @dpi: render at this resolution - * @spacing: space lines by this in points + * * @font: font to render with + * * @width: render within this many pixels across + * * @alignment: left/centre/right alignment + * * @dpi: render at this resolution + * * @spacing: space lines by this in points * * Draw the string @text to an image. @out is a one-band 8-bit * unsigned char image, with 0 for no text and 255 for text. Values inbetween diff --git a/libvips/create/tonelut.c b/libvips/create/tonelut.c index 096221ae..b0e724c2 100644 --- a/libvips/create/tonelut.c +++ b/libvips/create/tonelut.c @@ -315,16 +315,16 @@ vips_tonelut_init( VipsTonelut *lut ) * * Optional arguments: * - * @in_max: input range - * @out_max: output range - * @Lb: black-point [0-100] - * @Lw: white-point [0-100] - * @Ps: shadow point (eg. 0.2) - * @Pm: mid-tone point (eg. 0.5) - * @Ph: highlight point (eg. 0.8) - * @S: shadow adjustment (+/- 30) - * @M: mid-tone adjustment (+/- 30) - * @H: highlight adjustment (+/- 30) + * * @in_max: input range + * * @out_max: output range + * * @Lb: black-point [0-100] + * * @Lw: white-point [0-100] + * * @Ps: shadow point (eg. 0.2) + * * @Pm: mid-tone point (eg. 0.5) + * * @Ph: highlight point (eg. 0.8) + * * @S: shadow adjustment (+/- 30) + * * @M: mid-tone adjustment (+/- 30) + * * @H: highlight adjustment (+/- 30) * * vips_tonelut() generates a tone curve for the adjustment of image * levels. It is mostly designed for adjusting the L* part of a LAB image in diff --git a/libvips/create/xyz.c b/libvips/create/xyz.c index 852de729..e00b5b22 100644 --- a/libvips/create/xyz.c +++ b/libvips/create/xyz.c @@ -246,9 +246,9 @@ vips_xyz_init( VipsXyz *xyz ) * * Optional arguments: * - * @csize: size for third dimension - * @dsize: size for fourth dimension - * @esize: size for fifth dimension + * * @csize: size for third dimension + * * @dsize: size for fourth dimension + * * @esize: size for fifth dimension * * Create a two-band uint32 image where the elements in the first band have the * value of their x coordinate and elements in the second band have their y diff --git a/libvips/create/zone.c b/libvips/create/zone.c index 53f90494..1f44afdb 100644 --- a/libvips/create/zone.c +++ b/libvips/create/zone.c @@ -106,7 +106,7 @@ vips_zone_init( VipsZone *zone ) * * Optional arguments: * - * @uchar: output a uchar image + * * @uchar: output a uchar image * * Create a one-band image of a zone plate. * diff --git a/libvips/draw/draw_circle.c b/libvips/draw/draw_circle.c index a772e753..dee81e6f 100644 --- a/libvips/draw/draw_circle.c +++ b/libvips/draw/draw_circle.c @@ -294,7 +294,7 @@ vips_draw_circlev( VipsImage *image, * * Optional arguments: * - * @fill: fill the draw_circle + * * @fill: fill the draw_circle * * Draws a circle on @image. If @fill is %TRUE then the circle is filled, * otherwise a 1-pixel-wide perimeter is drawn. @@ -330,7 +330,7 @@ vips_draw_circle( VipsImage *image, * * Optional arguments: * - * @fill: fill the draw_circle + * * @fill: fill the draw_circle * * As vips_draw_circle(), but just takes a single double for @ink. * diff --git a/libvips/draw/draw_flood.c b/libvips/draw/draw_flood.c index 8f5f5029..7c1bf36f 100644 --- a/libvips/draw/draw_flood.c +++ b/libvips/draw/draw_flood.c @@ -685,12 +685,12 @@ vips_draw_floodv( VipsImage *image, * * Optional arguments: * - * @test: test this image - * @equal: fill while equal to edge - * @left: output left edge of bounding box of modified area - * @top: output top edge of bounding box of modified area - * @width: output width of bounding box of modified area - * @height: output height of bounding box of modified area + * * @test: test this image + * * @equal: fill while equal to edge + * * @left: output left edge of bounding box of modified area + * * @top: output top edge of bounding box of modified area + * * @width: output width of bounding box of modified area + * * @height: output height of bounding box of modified area * * Flood-fill @image with @ink, starting at position @x, @y. The filled area is * bounded by pixels that are equal to the ink colour, in other words, it @@ -736,12 +736,12 @@ vips_draw_flood( VipsImage *image, * * Optional arguments: * - * @test: test this image - * @equal: fill while equal to edge - * @left: output left edge of bounding box of modified area - * @top: output top edge of bounding box of modified area - * @width: output width of bounding box of modified area - * @height: output height of bounding box of modified area + * * @test: test this image + * * @equal: fill while equal to edge + * * @left: output left edge of bounding box of modified area + * * @top: output top edge of bounding box of modified area + * * @width: output width of bounding box of modified area + * * @height: output height of bounding box of modified area * * As vips_draw_flood(), but just takes a single double for @ink. * diff --git a/libvips/draw/draw_image.c b/libvips/draw/draw_image.c index c56bd486..3f9aa053 100644 --- a/libvips/draw/draw_image.c +++ b/libvips/draw/draw_image.c @@ -300,7 +300,7 @@ vips_draw_image_init( VipsDrawImage *draw_image ) * * Optional arguments: * - * @mode: how to combine pixels + * * @mode: how to combine pixels * * Draw @sub on top of @image at position @x, @y. The two images must have the * same Coding. If @sub has 1 band, the bands will be duplicated to match the diff --git a/libvips/draw/draw_rect.c b/libvips/draw/draw_rect.c index decb1cc5..261c6517 100644 --- a/libvips/draw/draw_rect.c +++ b/libvips/draw/draw_rect.c @@ -240,7 +240,7 @@ vips_draw_rectv( VipsImage *image, * * Optional arguments: * - * @fill: fill the rect + * * @fill: fill the rect * * Paint pixels within @left, @top, @width, @height in @image with @ink. If * @fill is zero, just paint a 1-pixel-wide outline. @@ -276,7 +276,7 @@ vips_draw_rect( VipsImage *image, * * Optional arguments: * - * @fill: fill the rect + * * @fill: fill the rect * * As vips_draw_rect(), but just take a single double for @ink. * diff --git a/libvips/foreign/csvload.c b/libvips/foreign/csvload.c index ad1b3646..d4deed4b 100644 --- a/libvips/foreign/csvload.c +++ b/libvips/foreign/csvload.c @@ -187,10 +187,10 @@ vips_foreign_load_csv_init( VipsForeignLoadCsv *csv ) * * Optional arguments: * - * @skip: skip this many lines at start of file - * @lines: read this many lines from file - * @whitespace: set of whitespace characters - * @separator: set of separator characters + * * @skip: skip this many lines at start of file + * * @lines: read this many lines from file + * * @whitespace: set of whitespace characters + * * @separator: set of separator characters * * Load a CSV (comma-separated values) file. The output image is always 1 * band (monochrome), #VIPS_FORMAT_DOUBLE. Use vips_bandfold() to turn diff --git a/libvips/foreign/csvsave.c b/libvips/foreign/csvsave.c index 11aa2ae6..483d2fb3 100644 --- a/libvips/foreign/csvsave.c +++ b/libvips/foreign/csvsave.c @@ -128,7 +128,7 @@ vips_foreign_save_csv_init( VipsForeignSaveCsv *csv ) * * Optional arguments: * - * @separator: separator string + * * @separator: separator string * * Writes the pixels in @in to the @filename as CSV (comma-separated values). * The image is written diff --git a/libvips/foreign/dzsave.c b/libvips/foreign/dzsave.c index 44b321e3..c4eee553 100644 --- a/libvips/foreign/dzsave.c +++ b/libvips/foreign/dzsave.c @@ -2047,16 +2047,16 @@ vips_foreign_save_dz_init( VipsForeignSaveDz *dz ) * * Optional arguments: * - * @layout; directory layout convention - * @suffix: suffix for tile tiles - * @overlap; set tile overlap - * @tile_size; set tile size - * @background: background colour - * @depth: how deep to make the pyramid - * @centre: centre the tiles - * @angle: rotate the image by this much - * @container: set container type - * @properties: write a properties file + * * @layout; directory layout convention + * * @suffix: suffix for tile tiles + * * @overlap; set tile overlap + * * @tile_size; set tile size + * * @background: background colour + * * @depth: how deep to make the pyramid + * * @centre: centre the tiles + * * @angle: rotate the image by this much + * * @container: set container type + * * @properties: write a properties file * * Save an image as a set of tiles at various resolutions. By default dzsave * uses DeepZoom layout -- use @layout to pick other conventions. diff --git a/libvips/foreign/foreign.c b/libvips/foreign/foreign.c index 2b7cffdc..2a92516b 100644 --- a/libvips/foreign/foreign.c +++ b/libvips/foreign/foreign.c @@ -1823,8 +1823,8 @@ vips_vipssave( VipsImage *in, const char *filename, ... ) * * Optional arguments: * - * @all_frames: %gboolean, load all frames in sequence - * @density: string, canvas resolution for rendering vector formats like SVG + * * @all_frames: %gboolean, load all frames in sequence + * * @density: string, canvas resolution for rendering vector formats like SVG * * Read in an image using libMagick, the ImageMagick library. This library can * read more than 80 file formats, including SVG, BMP, EPS, DICOM and many @@ -1870,8 +1870,8 @@ vips_magickload( const char *filename, VipsImage **out, ... ) * * Optional arguments: * - * @all_frames: %gboolean, load all frames in sequence - * @density: string, canvas resolution for rendering vector formats like SVG + * * @all_frames: %gboolean, load all frames in sequence + * * @density: string, canvas resolution for rendering vector formats like SVG * * Read an image memory block using libMagick into a VIPS image. Exactly as * vips_magickload(), but read from a memory source. @@ -1911,7 +1911,7 @@ vips_magickload_buffer( void *buf, size_t len, VipsImage **out, ... ) * * Optional arguments: * - * @page: int, load this page + * * @page: int, load this page * * Read a TIFF file into a VIPS image. It is a full baseline TIFF 6 reader, * with extensions for tiled images, multipage images, LAB colour space, @@ -1949,7 +1949,7 @@ vips_tiffload( const char *filename, VipsImage **out, ... ) * * Optional arguments: * - * @page: %gint, load this page + * * @page: %gint, load this page * * Read a TIFF-formatted memory block into a VIPS image. Exactly as * vips_tiffload(), but read from a memory source. @@ -1989,20 +1989,20 @@ vips_tiffload_buffer( void *buf, size_t len, VipsImage **out, ... ) * * Optional arguments: * - * @compression: use this #VipsForeignTiffCompression - * @Q: %gint quality factor - * @predictor: use this #VipsForeignTiffPredictor - * @profile: filename of ICC profile to attach - * @tile: set %TRUE to write a tiled tiff - * @tile_width: %gint for tile size - * @tile_height: %gint for tile size - * @pyramid: set %TRUE to write an image pyramid - * @squash: set %TRUE to squash 8-bit images down to 1 bit - * @miniswhite: set %TRUE to write 1-bit images as MINISWHITE - * @resunit: #VipsForeignTiffResunit for resolution unit - * @xres: %gdouble horizontal resolution in pixels/mm - * @yres: %gdouble vertical resolution in pixels/mm - * @bigtiff: set %TRUE to write a BigTiff file + * * @compression: use this #VipsForeignTiffCompression + * * @Q: %gint quality factor + * * @predictor: use this #VipsForeignTiffPredictor + * * @profile: filename of ICC profile to attach + * * @tile: set %TRUE to write a tiled tiff + * * @tile_width: %gint for tile size + * * @tile_height: %gint for tile size + * * @pyramid: set %TRUE to write an image pyramid + * * @squash: set %TRUE to squash 8-bit images down to 1 bit + * * @miniswhite: set %TRUE to write 1-bit images as MINISWHITE + * * @resunit: #VipsForeignTiffResunit for resolution unit + * * @xres: %gdouble horizontal resolution in pixels/mm + * * @yres: %gdouble vertical resolution in pixels/mm + * * @bigtiff: set %TRUE to write a BigTiff file * * Write a VIPS image to a file as TIFF. * @@ -2089,9 +2089,9 @@ vips_tiffsave( VipsImage *in, const char *filename, ... ) * * Optional arguments: * - * @shrink: %gint, shrink by this much on load - * @fail: %gboolean, fail on warnings - * @autorotate: %gboolean, use exif Orientation tag to rotate the image during load + * * @shrink: %gint, shrink by this much on load + * * @fail: %gboolean, fail on warnings + * * @autorotate: %gboolean, use exif Orientation tag to rotate the image during load * * Read a JPEG file into a VIPS image. It can read most 8-bit JPEG images, * including CMYK and YCbCr. @@ -2167,8 +2167,8 @@ vips_jpegload( const char *filename, VipsImage **out, ... ) * * Optional arguments: * - * @shrink: %gint, shrink by this much on load - * @fail: %gboolean, fail on warnings + * * @shrink: %gint, shrink by this much on load + * * @fail: %gboolean, fail on warnings * * Read a JPEG-formatted memory block into a VIPS image. Exactly as * vips_jpegload(), but read from a memory buffer. @@ -2208,15 +2208,15 @@ vips_jpegload_buffer( void *buf, size_t len, VipsImage **out, ... ) * * Optional arguments: * - * @Q: %gint, quality factor - * @profile: filename of ICC profile to attach - * @optimize_coding: %gboolean, compute optimal Huffman coding tables - * @interlace: %gboolean, write an interlaced (progressive) jpeg - * @strip: %gboolean, remove all metadata from image - * @no-subsample: %gboolean, disable chroma subsampling - * @trellis_quant: %gboolean, apply trellis quantisation to each 8x8 block - * @overshoot_deringing: %gboolean, overshoot samples with extreme values - * @optimize_scans: %gboolean, split DCT coefficients into separate scans + * * @Q: %gint, quality factor + * * @profile: filename of ICC profile to attach + * * @optimize_coding: %gboolean, compute optimal Huffman coding tables + * * @interlace: %gboolean, write an interlaced (progressive) jpeg + * * @strip: %gboolean, remove all metadata from image + * * @no-subsample: %gboolean, disable chroma subsampling + * * @trellis_quant: %gboolean, apply trellis quantisation to each 8x8 block + * * @overshoot_deringing: %gboolean, overshoot samples with extreme values + * * @optimize_scans: %gboolean, split DCT coefficients into separate scans * * Write a VIPS image to a file as JPEG. * @@ -2294,15 +2294,15 @@ vips_jpegsave( VipsImage *in, const char *filename, ... ) * * Optional arguments: * - * @Q: JPEG quality factor - * @profile: attach this ICC profile - * @optimize_coding: compute optimal Huffman coding tables - * @interlace: write an interlaced (progressive) jpeg - * @strip: remove all metadata from image - * @no-subsample: disable chroma subsampling - * @trellis_quant: %gboolean, apply trellis quantisation to each 8x8 block - * @overshoot_deringing: %gboolean, overshoot samples with extreme values - * @optimize_scans: %gboolean, split DCT coefficients into separate scans + * * @Q: JPEG quality factor + * * @profile: attach this ICC profile + * * @optimize_coding: compute optimal Huffman coding tables + * * @interlace: write an interlaced (progressive) jpeg + * * @strip: remove all metadata from image + * * @no-subsample: disable chroma subsampling + * * @trellis_quant: %gboolean, apply trellis quantisation to each 8x8 block + * * @overshoot_deringing: %gboolean, overshoot samples with extreme values + * * @optimize_scans: %gboolean, split DCT coefficients into separate scans * * As vips_jpegsave(), but save to a memory buffer. * @@ -2349,14 +2349,14 @@ vips_jpegsave_buffer( VipsImage *in, void **buf, size_t *len, ... ) * * Optional arguments: * - * @Q: JPEG quality factor - * @profile: attach this ICC profile - * @optimize_coding: compute optimal Huffman coding tables - * @strip: remove all metadata from image - * @no-subsample: disable chroma subsampling - * @trellis_quant: %gboolean, apply trellis quantisation to each 8x8 block - * @overshoot_deringing: %gboolean, overshoot samples with extreme values - * @optimize_scans: %gboolean, split DCT coefficients into separate scans + * * @Q: JPEG quality factor + * * @profile: attach this ICC profile + * * @optimize_coding: compute optimal Huffman coding tables + * * @strip: remove all metadata from image + * * @no-subsample: disable chroma subsampling + * * @trellis_quant: %gboolean, apply trellis quantisation to each 8x8 block + * * @overshoot_deringing: %gboolean, overshoot samples with extreme values + * * @optimize_scans: %gboolean, split DCT coefficients into separate scans * * As vips_jpegsave(), but save as a mime jpeg on stdout. * @@ -2385,7 +2385,7 @@ vips_jpegsave_mime( VipsImage *in, ... ) * * Optional arguments: * - * @shrink: %gint, shrink by this much on load + * * @shrink: %gint, shrink by this much on load * * Read a WebP file into a VIPS image. * @@ -2417,7 +2417,7 @@ vips_webpload( const char *filename, VipsImage **out, ... ) * * Optional arguments: * - * @shrink: %gint, shrink by this much on load + * * @shrink: %gint, shrink by this much on load * * Read a WebP-formatted memory block into a VIPS image. Exactly as * vips_webpload(), but read from a memory buffer. @@ -2505,12 +2505,12 @@ vips_webpsave( VipsImage *in, const char *filename, ... ) * * Optional arguments: * - * @Q: %gint quality factor - * @lossless: %gboolean enables lossless compression - * @preset: #VipsForeignWebpPreset choose lossy compression preset - * @smart_subsample: %gboolean enables high quality chroma subsampling - * @near_lossless: %gboolean use preprocessing in lossless mode (controlled by Q) - * @alpha_q: %gint set alpha quality in lossless mode + * * @Q: %gint quality factor + * * @lossless: %gboolean enables lossless compression + * * @preset: #VipsForeignWebpPreset choose lossy compression preset + * * @smart_subsample: %gboolean enables high quality chroma subsampling + * * @near_lossless: %gboolean use preprocessing in lossless mode (controlled by Q) + * * @alpha_q: %gint set alpha quality in lossless mode * * As vips_webpsave(), but save to a memory buffer. * @@ -2557,12 +2557,12 @@ vips_webpsave_buffer( VipsImage *in, void **buf, size_t *len, ... ) * * Optional arguments: * - * @Q: %gint quality factor - * @lossless: %gboolean enables lossless compression - * @preset: #VipsForeignWebpPreset choose lossy compression preset - * @smart_subsample: %gboolean enables high quality chroma subsampling - * @near_lossless: %gboolean use preprocessing in lossless mode (controlled by Q) - * @alpha_q: %gint set alpha quality in lossless mode + * * @Q: %gint quality factor + * * @lossless: %gboolean enables lossless compression + * * @preset: #VipsForeignWebpPreset choose lossy compression preset + * * @smart_subsample: %gboolean enables high quality chroma subsampling + * * @near_lossless: %gboolean use preprocessing in lossless mode (controlled by Q) + * * @alpha_q: %gint set alpha quality in lossless mode * * As vips_webpsave(), but save as a mime webp on stdout. * @@ -2623,9 +2623,9 @@ vips_openexrload( const char *filename, VipsImage **out, ... ) * * Optional arguments: * - * @level: load this level - * @associated: load this associated image - * @autocrop: crop to image bounds + * * @level: load this level + * * @associated: load this associated image + * * @autocrop: crop to image bounds * * Read a virtual slide supported by the OpenSlide library into a VIPS image. * OpenSlide supports images in Aperio, Hamamatsu, MIRAX, Sakura, Trestle, @@ -2726,8 +2726,6 @@ vips_fitssave( VipsImage *in, const char *filename, ... ) * @out: decompressed image * @...: %NULL-terminated list of optional named arguments * - * Optional arguments: - * * Read a PNG file into a VIPS image. It can read all png images, including 8- * and 16-bit images, 1 and 3 channel, with and without an alpha channel. * @@ -2798,10 +2796,10 @@ vips_pngload_buffer( void *buf, size_t len, VipsImage **out, ... ) * * Optional arguments: * - * @compression: compression level - * @interlace: interlace image - * @profile: ICC profile to embed - * @filter: #VipsForeignPngFilter row filter flag(s) + * * @compression: compression level + * * @interlace: interlace image + * * @profile: ICC profile to embed + * * @filter: #VipsForeignPngFilter row filter flag(s) * * Write a VIPS image to a file as PNG. * @@ -2854,10 +2852,10 @@ vips_pngsave( VipsImage *in, const char *filename, ... ) * * Optional arguments: * - * @compression: compression level - * @interlace: interlace image - * @profile: ICC profile to embed - * @filter: libpng row filter flag(s) + * * @compression: compression level + * * @interlace: interlace image + * * @profile: ICC profile to embed + * * @filter: libpng row filter flag(s) * * As vips_pngsave(), but save to a memory buffer. * @@ -2935,9 +2933,9 @@ vips_matload( const char *filename, VipsImage **out, ... ) * * Optional arguments: * - * @page: %gint, load this page, numbered from zero - * @dpi: %gdouble, render at this DPI - * @scale: %gdouble, scale render by this factor + * * @page: %gint, load this page, numbered from zero + * * @dpi: %gdouble, render at this DPI + * * @scale: %gdouble, scale render by this factor * * Render a PDF file into a VIPS image. Rendering uses the libpoppler library * and should be fast. @@ -2996,9 +2994,9 @@ vips_pdfload( const char *filename, VipsImage **out, ... ) * * Optional arguments: * - * @page: %gint, load this page, numbered from zero - * @dpi: %gdouble, render at this DPI - * @scale: %gdouble, scale render by this factor + * * @page: %gint, load this page, numbered from zero + * * @dpi: %gdouble, render at this DPI + * * @scale: %gdouble, scale render by this factor * * Read a PDF-formatted memory block into a VIPS image. Exactly as * vips_pdfload(), but read from a memory buffer. @@ -3038,8 +3036,8 @@ vips_pdfload_buffer( void *buf, size_t len, VipsImage **out, ... ) * * Optional arguments: * - * @dpi: %gdouble, render at this DPI - * @scale: %gdouble, scale render by this factor + * * @dpi: %gdouble, render at this DPI + * * @scale: %gdouble, scale render by this factor * * Render a SVG file into a VIPS image. Rendering uses the librsvg library * and should be fast. @@ -3076,8 +3074,8 @@ vips_svgload( const char *filename, VipsImage **out, ... ) * * Optional arguments: * - * @dpi: %gdouble, render at this DPI - * @scale: %gdouble, scale render by this factor + * * @dpi: %gdouble, render at this DPI + * * @scale: %gdouble, scale render by this factor * * Read a SVG-formatted memory block into a VIPS image. Exactly as * vips_svgload(), but read from a memory buffer. @@ -3117,7 +3115,7 @@ vips_svgload_buffer( void *buf, size_t len, VipsImage **out, ... ) * * Optional arguments: * - * @page: %ginit, page (frame) to read + * * @page: %ginit, page (frame) to read * * Read a GIF file into a VIPS image. Rendering uses the giflib library. * @@ -3152,7 +3150,7 @@ vips_gifload( const char *filename, VipsImage **out, ... ) * * Optional arguments: * - * @page: %ginit, page (frame) to read + * * @page: %ginit, page (frame) to read * * Read a GIF-formatted memory block into a VIPS image. Exactly as * vips_gifload(), but read from a memory buffer. diff --git a/libvips/foreign/ppmsave.c b/libvips/foreign/ppmsave.c index 178011af..f6ac8988 100644 --- a/libvips/foreign/ppmsave.c +++ b/libvips/foreign/ppmsave.c @@ -156,8 +156,8 @@ vips_foreign_save_ppm_init( VipsForeignSavePpm *ppm ) * * Optional arguments: * - * @ascii: save as ASCII rather than binary - * @squash: squash 8-bit images down to one bit + * * @ascii: save as ASCII rather than binary + * * @squash: squash 8-bit images down to one bit * * Write a VIPS image to a file as PPM. It can write 1, 8, 16 or * 32 bit unsigned integer images, float images, colour or monochrome, diff --git a/libvips/foreign/rawload.c b/libvips/foreign/rawload.c index 98cf4ec5..e6dd73d5 100644 --- a/libvips/foreign/rawload.c +++ b/libvips/foreign/rawload.c @@ -165,7 +165,7 @@ vips_foreign_load_raw_init( VipsForeignLoadRaw *raw ) * * Optional arguments: * - * @offset: offset in bytes from start of file + * * @offset: offset in bytes from start of file * * This operation mmaps the file, setting @out so that access to that * image will read from the file. diff --git a/libvips/freqfilt/invfft.c b/libvips/freqfilt/invfft.c index c3d8c45b..80ebfa30 100644 --- a/libvips/freqfilt/invfft.c +++ b/libvips/freqfilt/invfft.c @@ -276,7 +276,7 @@ vips_invfft_init( VipsInvfft *invfft ) * * Optional arguments: * - * @real: only output the real part + * * @real: only output the real part * * Transform an image from Fourier space to real space. The result is complex. * If you are OK with a real result, set @real, it's quicker. diff --git a/libvips/histogram/hist_equal.c b/libvips/histogram/hist_equal.c index 9c380c54..b6d527dc 100644 --- a/libvips/histogram/hist_equal.c +++ b/libvips/histogram/hist_equal.c @@ -138,7 +138,7 @@ vips_hist_equal_init( VipsHistEqual *equal ) * * Optional arguments: * - * @band: band to equalise + * * @band: band to equalise * * Histogram-equalise @in. Equalise using band @bandno, or if @bandno is -1, * equalise bands independently. diff --git a/libvips/histogram/maplut.c b/libvips/histogram/maplut.c index 14154c35..09631b95 100644 --- a/libvips/histogram/maplut.c +++ b/libvips/histogram/maplut.c @@ -735,7 +735,7 @@ vips_maplut_init( VipsMaplut *maplut ) * * Optional arguments: * - * @band: apply one-band @lut to this band of @in + * * @band: apply one-band @lut to this band of @in * * Map an image through another image acting as a LUT (Look Up Table). * The lut may have any type and the output image will be that type. diff --git a/libvips/histogram/stdif.c b/libvips/histogram/stdif.c index 6f0977b3..da701555 100644 --- a/libvips/histogram/stdif.c +++ b/libvips/histogram/stdif.c @@ -367,10 +367,10 @@ vips_stdif_init( VipsStdif *stdif ) * * Optional arguments: * - * @a: weight of new mean - * @m0: target mean - * @b: weight of new deviation - * @s0: target deviation + * * @a: weight of new mean + * * @m0: target mean + * * @b: weight of new deviation + * * @s0: target deviation * * vips_stdif() preforms statistical differencing according to the formula * given in page 45 of the book "An Introduction to Digital Image diff --git a/libvips/iofuncs/image.c b/libvips/iofuncs/image.c index 3fc640e5..bf33c6cc 100644 --- a/libvips/iofuncs/image.c +++ b/libvips/iofuncs/image.c @@ -1837,8 +1837,8 @@ vips_filename_get_options( const char *vips_filename ) * * Optional arguments: * - * @access: hint #VipsAccess mode to loader - * @disc: load via a temporary disc file + * * @access: hint #VipsAccess mode to loader + * * @disc: load via a temporary disc file * * vips_image_new_from_file() opens @name for reading. It can load files * in many image formats, including VIPS, TIFF, PNG, JPEG, FITS, Matlab, diff --git a/libvips/iofuncs/system.c b/libvips/iofuncs/system.c index 39ddff2d..6357f869 100644 --- a/libvips/iofuncs/system.c +++ b/libvips/iofuncs/system.c @@ -329,11 +329,11 @@ vips_system_init( VipsSystem *system ) * * Optional arguments: * - * @in: array of input images - * @out: output image - * @in_format: write input files like this - * @out_format: write output filename like this - * @log: stdout of command is returned here + * * @in: array of input images + * * @out: output image + * * @in_format: write input files like this + * * @out_format: write output filename like this + * * @log: stdout of command is returned here * * vips_system() runs a command, optionally passing a set of images in and * optionally getting an image back. The command's stdout is returned in @log. diff --git a/libvips/morphology/labelregions.c b/libvips/morphology/labelregions.c index ff9311d2..880b21be 100644 --- a/libvips/morphology/labelregions.c +++ b/libvips/morphology/labelregions.c @@ -149,7 +149,7 @@ vips_labelregions_init( VipsLabelregions *labelregions ) * * Optional arguments: * - * @segments: return number of regions found here + * * @segments: return number of regions found here * * Repeatedly scans @in for regions of 4-connected pixels * with the same pixel value. Every time a region is discovered, those diff --git a/libvips/mosaicing/global_balance.c b/libvips/mosaicing/global_balance.c index f1c4630f..053330b1 100644 --- a/libvips/mosaicing/global_balance.c +++ b/libvips/mosaicing/global_balance.c @@ -1809,8 +1809,8 @@ vips_globalbalance_init( VipsGlobalbalance *globalbalance ) * * Optional arguments: * - * @gamma: gamma of source images - * @int_output: %TRUE for integer image output + * * @gamma: gamma of source images + * * @int_output: %TRUE for integer image output * * vips_globalbalance() can be used to remove contrast differences in * an assembled mosaic. diff --git a/libvips/mosaicing/match.c b/libvips/mosaicing/match.c index 21fa91ca..60b77594 100644 --- a/libvips/mosaicing/match.c +++ b/libvips/mosaicing/match.c @@ -328,10 +328,10 @@ vips_match_init( VipsMatch *match ) * * Optional arguments: * - * @search: search to improve tie-points - * @hwindow: half window size - * @harea: half search size - * @interpolate: interpolate pixels with this + * * @search: search to improve tie-points + * * @hwindow: half window size + * * @harea: half search size + * * @interpolate: interpolate pixels with this * * Scale, rotate and translate @sec so that the tie-points line up. * diff --git a/libvips/mosaicing/merge.c b/libvips/mosaicing/merge.c index bf7b1e9c..3062c760 100644 --- a/libvips/mosaicing/merge.c +++ b/libvips/mosaicing/merge.c @@ -171,7 +171,7 @@ vips_merge_init( VipsMerge *merge ) * * Optional arguments: * - * @mblend: maximum blend size + * * @mblend: maximum blend size * * This operation joins two images left-right (with @ref on the left) or * up-down (with @ref above) with a smooth seam. diff --git a/libvips/mosaicing/mosaic.c b/libvips/mosaicing/mosaic.c index cea6cd90..c8897e50 100644 --- a/libvips/mosaicing/mosaic.c +++ b/libvips/mosaicing/mosaic.c @@ -324,10 +324,10 @@ vips_mosaic_init( VipsMosaic *mosaic ) * * Optional arguments: * - * @bandno: band to search for features - * @hwindow: half window size - * @harea: half search size - * @mblend: maximum blend size + * * @bandno: band to search for features + * * @hwindow: half window size + * * @harea: half search size + * * @mblend: maximum blend size * * This operation joins two images left-right (with @ref on the left) or * top-bottom (with @ref above) given an approximate overlap. diff --git a/libvips/mosaicing/mosaic1.c b/libvips/mosaicing/mosaic1.c index 2fa468f7..651db3c9 100644 --- a/libvips/mosaicing/mosaic1.c +++ b/libvips/mosaicing/mosaic1.c @@ -635,12 +635,12 @@ vips_mosaic1_init( VipsMosaic1 *mosaic1 ) * * Optional arguments: * - * @search: search to improve tie-points - * @hwindow: half window size - * @harea: half search size - * @interpolate: interpolate pixels with this - * @mblend: maximum blend size - * @bandno: band to search for features + * * @search: search to improve tie-points + * * @hwindow: half window size + * * @harea: half search size + * * @interpolate: interpolate pixels with this + * * @mblend: maximum blend size + * * @bandno: band to search for features * * This operation joins two images top-bottom (with @sec on the right) * or left-right (with @sec at the bottom) diff --git a/libvips/resample/affine.c b/libvips/resample/affine.c index de9ded32..d67c184b 100644 --- a/libvips/resample/affine.c +++ b/libvips/resample/affine.c @@ -623,12 +623,12 @@ vips_affine_init( VipsAffine *affine ) * * Optional arguments: * - * @interpolate: interpolate pixels with this - * @oarea: output rectangle - * @idx: input horizontal offset - * @idy: input vertical offset - * @odx: output horizontal offset - * @ody: output vertical offset + * * @interpolate: interpolate pixels with this + * * @oarea: output rectangle + * * @idx: input horizontal offset + * * @idy: input vertical offset + * * @odx: output horizontal offset + * * @ody: output vertical offset * * This operator performs an affine transform on an image using @interpolate. * diff --git a/libvips/resample/mapim.c b/libvips/resample/mapim.c index 9187153a..8592363e 100644 --- a/libvips/resample/mapim.c +++ b/libvips/resample/mapim.c @@ -415,7 +415,7 @@ vips_mapim_init( VipsMapim *mapim ) * * Optional arguments: * - * @interpolate: interpolate pixels with this + * * @interpolate: interpolate pixels with this * * This operator resamples @in using @index to look up pixels. @out is * the same size as @index, with each pixel being fetched from that position in diff --git a/libvips/resample/quadratic.c b/libvips/resample/quadratic.c index e4741af8..8db0fd6a 100644 --- a/libvips/resample/quadratic.c +++ b/libvips/resample/quadratic.c @@ -371,7 +371,7 @@ vips_quadratic_init( VipsQuadratic *quadratic ) * * Optional arguments: * - * @interpolate: use this interpolator (default bilinear) + * * @interpolate: use this interpolator (default bilinear) * * This operation is unfinished and unusable, sorry. * diff --git a/libvips/resample/reduce.c b/libvips/resample/reduce.c index 6f63bcda..1304e609 100644 --- a/libvips/resample/reduce.c +++ b/libvips/resample/reduce.c @@ -146,7 +146,7 @@ vips_reduce_init( VipsReduce *reduce ) * * Optional arguments: * - * @kernel: #VipsKernel to use to interpolate (default: lanczos3) + * * @kernel: #VipsKernel to use to interpolate (default: lanczos3) * * Reduce @in by a pair of factors with a pair of 1D interpolators. This * will not work well for shrink factors greater than two. diff --git a/libvips/resample/resize.c b/libvips/resample/resize.c index bff34d7c..34df769a 100644 --- a/libvips/resample/resize.c +++ b/libvips/resample/resize.c @@ -336,8 +336,8 @@ vips_resize_init( VipsResize *resize ) * * Optional arguments: * - * @vscale: vertical scale factor - * @kernel: #VipsKernel to reduce with + * * @vscale: vertical scale factor + * * @kernel: #VipsKernel to reduce with * * Resize an image. When upsizing (@scale > 1), the image is simply block * upsized. When downsizing, the diff --git a/libvips/resample/similarity.c b/libvips/resample/similarity.c index 9259cbdd..a0e59e86 100644 --- a/libvips/resample/similarity.c +++ b/libvips/resample/similarity.c @@ -236,13 +236,13 @@ vips_similarity_init( VipsSimilarity *similarity ) * * Optional arguments: * - * @scale: scale by this factor - * @angle: rotate by this many degrees anticlockwise - * @interpolate: interpolate pixels with this - * @idx: input horizontal offset - * @idy: input vertical offset - * @odx: output horizontal offset - * @ody: output vertical offset + * * @scale: scale by this factor + * * @angle: rotate by this many degrees anticlockwise + * * @interpolate: interpolate pixels with this + * * @idx: input horizontal offset + * * @idy: input vertical offset + * * @odx: output horizontal offset + * * @ody: output vertical offset * * This operator calls vips_affine() for you, calculating the matrix for the * affine transform from @scale and @angle. Other parameters are passed on to From 37c716be89c9228af39780d5e44bd96796e133fb Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Tue, 3 May 2016 09:36:49 +0100 Subject: [PATCH 13/34] more webp doc improvements --- TODO | 2 -- libvips/foreign/foreign.c | 11 ++++++----- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/TODO b/TODO index c16cf38d..cf0dcd7a 100644 --- a/TODO +++ b/TODO @@ -1,5 +1,3 @@ -- add "*" before each optional arg description - - I like the new int mask creator in reducev, can we use it in im_vips2imask() as well? diff --git a/libvips/foreign/foreign.c b/libvips/foreign/foreign.c index 2a92516b..7389fbf5 100644 --- a/libvips/foreign/foreign.c +++ b/libvips/foreign/foreign.c @@ -2466,18 +2466,19 @@ vips_webpload_buffer( void *buf, size_t len, VipsImage **out, ... ) * * Write an image to a file in WebP format. * - * Use @Q to set the WebP quality factor. It has the range 0 - 100, with the + * By default, images are saved in lossy format, with + * @Q giving the WebP quality factor. It has the range 0 - 100, with the * default 75. * - * Use @preset to hint the image type to lossy compressor. The default is + * Use @preset to hint the image type to the lossy compressor. The default is * #VIPS_FOREIGN_WEBP_PRESET_DEFAULT. - * * Set @smart_subsample to enable high quality chroma subsampling. - * * Use @alpha_q to set the quality for the alpha channel in lossy mode. It has * the range 1 - 100, with the default 100. * - * Set @lossless to enable lossless save. + * Set @lossless to use lossless compression, or combine @near_lossless + * with @Q 80, 60, 40 or 20 to apply increasing amounts of preprocessing + * which improves the near-lossless compression ratio by up to 50%. * * See also: vips_webpload(), vips_image_write_to_file(). * From c081f51ffc7c0076c90f58945f9469a54b2982d5 Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Wed, 4 May 2016 13:20:19 +0100 Subject: [PATCH 14/34] fix a compiler warning --- libvips/colour/colour.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libvips/colour/colour.c b/libvips/colour/colour.c index 848032d4..ed5666a1 100644 --- a/libvips/colour/colour.c +++ b/libvips/colour/colour.c @@ -228,7 +228,6 @@ vips_colour_gen( VipsRegion *or, { VipsRegion **ir = (VipsRegion **) seq; VipsColour *colour = VIPS_COLOUR( b ); - VipsObjectClass *object_class = VIPS_OBJECT_GET_CLASS( colour ); VipsColourClass *class = VIPS_COLOUR_GET_CLASS( colour ); VipsRect *r = &or->valid; @@ -252,7 +251,7 @@ vips_colour_gen( VipsRegion *or, VIPS_GATE_STOP( "vips_colour_gen: work" ); - VIPS_COUNT_PIXELS( or, object_class->nickname ); + VIPS_COUNT_PIXELS( or, VIPS_OBJECT_GET_CLASS( colour )->nickname ); return( 0 ); } From 1366d0af6d4be19983fa678cb4f84270f9795ffe Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Thu, 5 May 2016 09:14:58 +0100 Subject: [PATCH 15/34] note --with-modules flag for IM --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index b9b0ff3e..3f5112e9 100644 --- a/README.md +++ b/README.md @@ -234,6 +234,10 @@ If available, libvips adds support for loading all libMagick-supported image file types. Use `--with-magickpackage=GraphicsMagick` to build against graphicsmagick instead. +Imagemagick 6.9+ needs to have been built with `--with-modules`. Most packaged +IMs are, I think, but if you are rolling your own, you'll need to pass +this flag to configure. + ### pangoft2 If available, libvips adds support for text rendering. You need the From c5fa0e1feb75c76b7a1eed6c859acd6e363a5561 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20Bu=CC=88nemann?= Date: Sat, 7 May 2016 03:13:52 +0200 Subject: [PATCH 16/34] Add mozjpeg quant_table option to jpegsave This allows to choose from several predefined quantization tables when libvips is compiled against mozjpeg 3.0+. Tuning the quantization table helps to improve file size in the higher quality range and avoid artefacts in the lower range. --- libvips/foreign/foreign.c | 27 +++++++++++++++++++++++++++ libvips/foreign/jpegsave.c | 20 +++++++++++++++++--- libvips/foreign/vips2jpeg.c | 33 ++++++++++++++++++++++++++------- libvips/foreign/vipsjpeg.h | 4 ++-- 4 files changed, 72 insertions(+), 12 deletions(-) diff --git a/libvips/foreign/foreign.c b/libvips/foreign/foreign.c index 7389fbf5..10fb231c 100644 --- a/libvips/foreign/foreign.c +++ b/libvips/foreign/foreign.c @@ -2217,6 +2217,7 @@ vips_jpegload_buffer( void *buf, size_t len, VipsImage **out, ... ) * * @trellis_quant: %gboolean, apply trellis quantisation to each 8x8 block * * @overshoot_deringing: %gboolean, overshoot samples with extreme values * * @optimize_scans: %gboolean, split DCT coefficients into separate scans + * * @quant_table: %gint, quantization table index * * Write a VIPS image to a file as JPEG. * @@ -2268,6 +2269,30 @@ vips_jpegload_buffer( void *buf, size_t len, VipsImage **out, ... ) * (e.g. mozjpeg >= 3.0), split the spectrum of DCT coefficients into * separate scans. Reduces file size but increases compression time. * + * If @quant_table is set and the version of libjpeg supports it + * (e.g. mozjpeg >= 3.0) it selects the quantization table to use: + * + * * 0 Tables from JPEG Annex K (vips and libjpeg default) + * * 1 Flat table + * * 2 Table tuned for MSSIM on Kodak image set + * * 3 Table from ImageMagick by N. Robidoux (current mozjpeg default) + * * 4 Table tuned for PSNR-HVS-M on Kodak image set + * * 5 Table from Relevance of Human Vision to JPEG-DCT Compression (1992) + * * 6 Table from DCTune Perceptual Optimization of Compressed Dental X-Rays (1997) + * * 7 Table from A Visual Detection Model for DCT Coefficient Quantization (1993) + * * 8 Table from An Improved Detection Model for DCT Coefficient Quantization (1993) + * + * Quantization table 0 is the default in vips and libjpeg(-turbo), but it + * tends to favor detail over color accuracy, producting colored patches and + * stripes as well as heavy banding in flat areas at high compression ratios. + * Quantization table 2 is a good candidate to try if the default quantization + * table produces banding or color shifts and is well suited for hires images. + * Quantization table 3 is the default in mozjpeg and has been tuned to produce + * good results at the default quality setting; banding at high compression. + * Quantization table 4 is the most accurate at the cost of compression ratio. + * Tables 5-7 are based on older research papers, but generally achieve worse + * compression ratios and/or quality than 2 or 4. + * * See also: vips_jpegsave_buffer(), vips_image_write_to_file(). * * Returns: 0 on success, -1 on error. @@ -2303,6 +2328,7 @@ vips_jpegsave( VipsImage *in, const char *filename, ... ) * * @trellis_quant: %gboolean, apply trellis quantisation to each 8x8 block * * @overshoot_deringing: %gboolean, overshoot samples with extreme values * * @optimize_scans: %gboolean, split DCT coefficients into separate scans + * * @quant_table: %gint, quantization table index * * As vips_jpegsave(), but save to a memory buffer. * @@ -2357,6 +2383,7 @@ vips_jpegsave_buffer( VipsImage *in, void **buf, size_t *len, ... ) * * @trellis_quant: %gboolean, apply trellis quantisation to each 8x8 block * * @overshoot_deringing: %gboolean, overshoot samples with extreme values * * @optimize_scans: %gboolean, split DCT coefficients into separate scans + * * @quant_table: %gint, quantization table index * * As vips_jpegsave(), but save as a mime jpeg on stdout. * diff --git a/libvips/foreign/jpegsave.c b/libvips/foreign/jpegsave.c index 2cc29a6a..4fac9b99 100644 --- a/libvips/foreign/jpegsave.c +++ b/libvips/foreign/jpegsave.c @@ -103,6 +103,10 @@ typedef struct _VipsForeignSaveJpeg { */ gboolean optimize_scans; + /* Use predefined quantization table with given index. + */ + int quant_table; + } VipsForeignSaveJpeg; typedef VipsForeignSaveClass VipsForeignSaveJpegClass; @@ -194,6 +198,13 @@ vips_foreign_save_jpeg_class_init( VipsForeignSaveJpegClass *class ) G_STRUCT_OFFSET( VipsForeignSaveJpeg, optimize_scans ), FALSE ); + VIPS_ARG_INT( class, "quant_table", 18, + _( "Quantization table" ), + _( "Use predefined quantization table with given index" ), + VIPS_ARGUMENT_OPTIONAL_INPUT, + G_STRUCT_OFFSET( VipsForeignSaveJpeg, quant_table ), + 0, 8, 0 ); + } static void @@ -230,7 +241,8 @@ vips_foreign_save_jpeg_file_build( VipsObject *object ) if( vips__jpeg_write_file( save->ready, file->filename, jpeg->Q, jpeg->profile, jpeg->optimize_coding, jpeg->interlace, save->strip, jpeg->no_subsample, - jpeg->trellis_quant, jpeg->overshoot_deringing, jpeg->optimize_scans) ) + jpeg->trellis_quant, jpeg->overshoot_deringing, + jpeg->optimize_scans, jpeg->quant_table ) ) return( -1 ); return( 0 ); @@ -294,7 +306,8 @@ vips_foreign_save_jpeg_buffer_build( VipsObject *object ) if( vips__jpeg_write_buffer( save->ready, &obuf, &olen, jpeg->Q, jpeg->profile, jpeg->optimize_coding, jpeg->interlace, save->strip, jpeg->no_subsample, - jpeg->trellis_quant, jpeg->overshoot_deringing, jpeg->optimize_scans) ) + jpeg->trellis_quant, jpeg->overshoot_deringing, + jpeg->optimize_scans, jpeg->quant_table ) ) return( -1 ); blob = vips_blob_new( (VipsCallbackFn) vips_free, obuf, olen ); @@ -357,7 +370,8 @@ vips_foreign_save_jpeg_mime_build( VipsObject *object ) if( vips__jpeg_write_buffer( save->ready, &obuf, &olen, jpeg->Q, jpeg->profile, jpeg->optimize_coding, jpeg->interlace, save->strip, jpeg->no_subsample, - jpeg->trellis_quant, jpeg->overshoot_deringing, jpeg->optimize_scans) ) + jpeg->trellis_quant, jpeg->overshoot_deringing, + jpeg->optimize_scans, jpeg->quant_table ) ) return( -1 ); printf( "Content-length: %zu\r\n", olen ); diff --git a/libvips/foreign/vips2jpeg.c b/libvips/foreign/vips2jpeg.c index d714cfc9..0c7bda5b 100644 --- a/libvips/foreign/vips2jpeg.c +++ b/libvips/foreign/vips2jpeg.c @@ -966,7 +966,7 @@ static int write_vips( Write *write, int qfac, const char *profile, gboolean optimize_coding, gboolean progressive, gboolean strip, gboolean no_subsample, gboolean trellis_quant, - gboolean overshoot_deringing, gboolean optimize_scans ) + gboolean overshoot_deringing, gboolean optimize_scans, int quant_table ) { VipsImage *in; J_COLOR_SPACE space; @@ -1022,10 +1022,9 @@ write_vips( Write *write, int qfac, const char *profile, JINT_COMPRESS_PROFILE, JCP_FASTEST ); #endif - /* Rest to default. + /* Reset to default. */ jpeg_set_defaults( &write->cinfo ); - jpeg_set_quality( &write->cinfo, qfac, TRUE ); /* Compute optimal Huffman coding tables. */ @@ -1077,6 +1076,20 @@ write_vips( Write *write, int qfac, const char *profile, vips_warn( "vips2jpeg", "%s", _( "Ignoring optimize_scans for baseline" ) ); } + + /* Use predefined quantization table. + */ + if( quant_table > 0 ) { + if( jpeg_c_int_param_supported( &write->cinfo, + JINT_BASE_QUANT_TBL_IDX ) ) + jpeg_c_set_int_param( &write->cinfo, + JINT_BASE_QUANT_TBL_IDX, quant_table ); + else + vips_warn( "vips2jpeg", + "%s", _( "Setting quant_table unsupported" ) ); + } + vips_warn( "vips2jpeg", "quant_table %d", + jpeg_c_get_int_param( &write->cinfo, JINT_BASE_QUANT_TBL_IDX ) ); #else /* Using jpeglib.h without extension parameters, warn of ignored * options. @@ -1088,8 +1101,14 @@ write_vips( Write *write, int qfac, const char *profile, "%s", _( "Ignoring overshoot_deringing" ) ); if( optimize_scans ) vips_warn( "vips2jpeg", "%s", _( "Ignoring optimize_scans" ) ); + if( quant_table > 0 ) + vips_warn( "vips2jpeg", "%s", _( "Ignoring quant_table" ) ); #endif + /* Set compression quality. Must be called after setting params above. + */ + jpeg_set_quality( &write->cinfo, qfac, TRUE ); + /* Enable progressive write. */ if( progressive ) @@ -1160,7 +1179,7 @@ vips__jpeg_write_file( VipsImage *in, const char *filename, int Q, const char *profile, gboolean optimize_coding, gboolean progressive, gboolean strip, gboolean no_subsample, gboolean trellis_quant, - gboolean overshoot_deringing, gboolean optimize_scans ) + gboolean overshoot_deringing, gboolean optimize_scans, int quant_table ) { Write *write; @@ -1192,7 +1211,7 @@ vips__jpeg_write_file( VipsImage *in, */ if( write_vips( write, Q, profile, optimize_coding, progressive, strip, no_subsample, - trellis_quant, overshoot_deringing, optimize_scans ) ) { + trellis_quant, overshoot_deringing, optimize_scans, quant_table ) ) { write_destroy( write ); return( -1 ); } @@ -1446,7 +1465,7 @@ vips__jpeg_write_buffer( VipsImage *in, void **obuf, size_t *olen, int Q, const char *profile, gboolean optimize_coding, gboolean progressive, gboolean strip, gboolean no_subsample, gboolean trellis_quant, - gboolean overshoot_deringing, gboolean optimize_scans ) + gboolean overshoot_deringing, gboolean optimize_scans, int quant_table ) { Write *write; @@ -1477,7 +1496,7 @@ vips__jpeg_write_buffer( VipsImage *in, */ if( write_vips( write, Q, profile, optimize_coding, progressive, strip, no_subsample, - trellis_quant, overshoot_deringing, optimize_scans ) ) { + trellis_quant, overshoot_deringing, optimize_scans, quant_table ) ) { write_destroy( write ); return( -1 ); diff --git a/libvips/foreign/vipsjpeg.h b/libvips/foreign/vipsjpeg.h index 9c86cb5c..a9bf86e6 100644 --- a/libvips/foreign/vipsjpeg.h +++ b/libvips/foreign/vipsjpeg.h @@ -41,12 +41,12 @@ int vips__jpeg_write_file( VipsImage *in, const char *filename, int Q, const char *profile, gboolean optimize_coding, gboolean progressive, gboolean strip, gboolean no_subsample, gboolean trellis_quant, - gboolean overshoot_deringing, gboolean optimize_scans ); + gboolean overshoot_deringing, gboolean optimize_scans, int quant_table ); int vips__jpeg_write_buffer( VipsImage *in, void **obuf, size_t *olen, int Q, const char *profile, gboolean optimize_coding, gboolean progressive, gboolean strip, gboolean no_subsample, gboolean trellis_quant, - gboolean overshoot_deringing, gboolean optimize_scans ); + gboolean overshoot_deringing, gboolean optimize_scans, int quant_table ); int vips__isjpeg_buffer( const void *buf, size_t len ); int vips__isjpeg( const char *filename ); From 948d1103d4062c67afe3d92f639b2ee730922a33 Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Sat, 7 May 2016 19:53:00 +0100 Subject: [PATCH 17/34] note more webp tests needed --- TODO | 2 ++ libvips/resample/resize.c | 4 +--- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/TODO b/TODO index cf0dcd7a..18b3339a 100644 --- a/TODO +++ b/TODO @@ -1,3 +1,5 @@ +- add more webp tests to py suite + - I like the new int mask creator in reducev, can we use it in im_vips2imask() as well? diff --git a/libvips/resample/resize.c b/libvips/resample/resize.c index 34df769a..c35b1ef3 100644 --- a/libvips/resample/resize.c +++ b/libvips/resample/resize.c @@ -309,9 +309,7 @@ vips_resize_class_init( VipsResizeClass *class ) G_STRUCT_OFFSET( VipsResize, idy ), -10000000, 10000000, 0 ); - /* We used to let people set the interpolator, but it's not clear this - * was useful. Anyway, vips_reduce() no longer has an interpolator - * param. + /* It's a kernel now we use vips_reduce() not vips_affine(). */ VIPS_ARG_INTERPOLATE( class, "interpolate", 2, _( "Interpolate" ), From b03ad51ae36586f1925c2c72d32972ddae57d105 Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Sat, 7 May 2016 21:01:04 +0100 Subject: [PATCH 18/34] oops, fix error reporting from giflib --- libvips/foreign/gifload.c | 36 +++++++++++++++++++++++++++--------- 1 file changed, 27 insertions(+), 9 deletions(-) diff --git a/libvips/foreign/gifload.c b/libvips/foreign/gifload.c index 202ad674..2481526d 100644 --- a/libvips/foreign/gifload.c +++ b/libvips/foreign/gifload.c @@ -153,15 +153,33 @@ vips_foreign_load_gif_errstr( int error_code ) #endif /*HAVE_GIFLIB_5*/ } +static void +vips_foreign_load_gif_error_vips( VipsForeignLoadGif *gif, int error ) +{ + VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( gif ); + + const char *message; + + if( (message = vips_foreign_load_gif_errstr( gif->file->Error )) ) + vips_error( class->nickname, "%s", message ); +} + static void vips_foreign_load_gif_error( VipsForeignLoadGif *gif ) { + int error; + + error = 0; + #ifdef HAVE_GIFLIB_5 if( gif->file ) - vips_foreign_load_gif_errstr( gif->file->Error ); + error = gif->file->Error; #else - vips_foreign_load_gif_errstr( GifLastError() ); + error = GifLastError(); #endif + + if( error ) + vips_foreign_load_gif_error_vips( gif, error ); } static void @@ -172,13 +190,13 @@ vips_foreign_load_gif_close( VipsForeignLoadGif *gif ) int error; if( DGifCloseFile( gif->file, &error ) ) - vips_foreign_load_gif_errstr( error ); + vips_foreign_load_gif_error_vips( gif, error ); gif->file = NULL; } #else if( gif->file ) { if( DGifCloseFile( gif->file ) ) - vips_foreign_load_gif_errstr( GifLastError() ); + vips_foreign_load_gif_error_vips( gif, GifLastError() ); gif->file = NULL; } #endif @@ -194,13 +212,13 @@ vips_foreign_load_gif_open( VipsForeignLoadGif *gif, const char *filename ) int error; if( !(gif->file = DGifOpenFileName( filename, &error )) ) { - vips_foreign_load_gif_errstr( error ); + vips_foreign_load_gif_error_vips( gif, error ); return( -1 ); } } #else if( !(gif->file = DGifOpenFileName( filename )) ) { - vips_foreign_load_gif_errstr( GifLastError() ); + vips_foreign_load_gif_error_vips( gif, GifLastError() ); return( -1 ); } #endif @@ -218,13 +236,13 @@ vips_foreign_load_gif_open_buffer( VipsForeignLoadGif *gif, InputFunc read_fn ) int error; if( !(gif->file = DGifOpen( gif, read_fn, &error )) ) { - vips_foreign_load_gif_errstr( error ); + vips_foreign_load_gif_error_vips( gif, error ); return( -1 ); } } #else if( !(gif->file = DGifOpen( gif, read_fn )) ) { - vips_foreign_load_gif_errstr( GifLastError() ); + vips_foreign_load_gif_error_vips( gif, GifLastError() ); return( -1 ); } #endif @@ -435,7 +453,7 @@ vips_foreign_load_gif_load( VipsForeignLoad *load ) GifByteType *extension; int ext_code; - if( DGifGetRecordType( gif->file, &record) == GIF_ERROR ) { + if( DGifGetRecordType( gif->file, &record ) == GIF_ERROR ) { vips_foreign_load_gif_error( gif ); return( -1 ); } From a342fdbeeb60357349dfc33a99fba319af653f3f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20Bu=CC=88nemann?= Date: Sun, 8 May 2016 03:23:00 +0200 Subject: [PATCH 19/34] Fix configure check for giflib4 This uses a combination of the old giflib4 and the new giflib5 checks. --- acinclude.m4 | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/acinclude.m4 b/acinclude.m4 index 4f17b2ab..568c2734 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -631,14 +631,26 @@ if test "$GIFLIB_LIBS" = ""; then INCLUDES="$GIFLIB_INCLUDES $INCLUDES" # Try the standard search path first - AC_TRY_LINK([#include ],[EGifSetGifVersion(0,0)], [ + AC_TRY_LINK([#include ],[ + #if defined(GIFLIB_MAJOR) && GIFLIB_MAJOR > 4 + EGifSetGifVersion(0,0); + #else + GifLastError(); + #endif + ], [ GIFLIB_LIBS="-lgif" ], [ # giflib is not in the standard search path, try $prefix LIBS="-L${prefix}/lib $LIBS" - AC_TRY_LINK([#include ],[EGifSetGifVersion(0,0)], [ + AC_TRY_LINK([#include ],[ + #if defined(GIFLIB_MAJOR) && GIFLIB_MAJOR > 4 + EGifSetGifVersion(0,0); + #else + GifLastError(); + #endif + ], [ GIFLIB_LIBS="-L${prefix}/lib -lgif" ], [ GIFLIB_LIBS=no From 379b69fda881d487fbf117b7865876c30aa2bfef Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Sun, 8 May 2016 10:02:34 +0100 Subject: [PATCH 20/34] note on test suite failure --- TODO | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/TODO b/TODO index cf0dcd7a..1f1a7cfc 100644 --- a/TODO +++ b/TODO @@ -1,3 +1,10 @@ +- the gif tests in the suite sometimes fail with giflib5 because of an + uninitialized struct in giflib, see + + https://sourceforge.net/p/giflib/bugs/94/ + + sadly ubuntu 16.04 only comes with giflib5, and giflib5 is currently broken + - I like the new int mask creator in reducev, can we use it in im_vips2imask() as well? From f7a6a02ee8017f02cde73af6da4d319d64841b5a Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Sun, 8 May 2016 11:02:21 +0100 Subject: [PATCH 21/34] fix giflib4 detection and a problem in giflib4 error handling --- ChangeLog | 1 + acinclude.m4 | 4 ++-- libvips/foreign/gifload.c | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index cbb50c50..1b926428 100644 --- a/ChangeLog +++ b/ChangeLog @@ -5,6 +5,7 @@ - add giflib5 support - allow resize >1 on one axis, <1 on the other - vips_resize has an optional @kernel argument +- fix giflib4 detection [felixbuenemann] 29/1/16 started 8.3 - add vips_reduce*() ... a fast path for affine downsize diff --git a/acinclude.m4 b/acinclude.m4 index 4f17b2ab..d1bbc58f 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -631,14 +631,14 @@ if test "$GIFLIB_LIBS" = ""; then INCLUDES="$GIFLIB_INCLUDES $INCLUDES" # Try the standard search path first - AC_TRY_LINK([#include ],[EGifSetGifVersion(0,0)], [ + AC_TRY_LINK([#include ],[DGifSlurp(0)], [ GIFLIB_LIBS="-lgif" ], [ # giflib is not in the standard search path, try $prefix LIBS="-L${prefix}/lib $LIBS" - AC_TRY_LINK([#include ],[EGifSetGifVersion(0,0)], [ + AC_TRY_LINK([#include ],[DGifSlurp(0)], [ GIFLIB_LIBS="-L${prefix}/lib -lgif" ], [ GIFLIB_LIBS=no diff --git a/libvips/foreign/gifload.c b/libvips/foreign/gifload.c index 2481526d..5fc317db 100644 --- a/libvips/foreign/gifload.c +++ b/libvips/foreign/gifload.c @@ -160,7 +160,7 @@ vips_foreign_load_gif_error_vips( VipsForeignLoadGif *gif, int error ) const char *message; - if( (message = vips_foreign_load_gif_errstr( gif->file->Error )) ) + if( (message = vips_foreign_load_gif_errstr( error )) ) vips_error( class->nickname, "%s", message ); } From bec6b174c99bb8121318834b79618cf948447ff6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20Bu=CC=88nemann?= Date: Sun, 8 May 2016 22:39:08 +0200 Subject: [PATCH 22/34] Fix poppler version requirement, add loader check This fixes the poppler-glib version requirement to version 0.16, which is the lowest version that compiles and works properly with pdfload. Also added a check for pdfload and enabled testing on Travis CI. --- .travis.yml | 2 +- configure.ac | 8 ++++---- test/images/blankpage.pdf | 37 +++++++++++++++++++++++++++++++++++++ test/images/blankpage.png | Bin 0 -> 3795 bytes test/test_formats.sh | 8 ++++++++ 5 files changed, 50 insertions(+), 5 deletions(-) create mode 100755 test/images/blankpage.pdf create mode 100644 test/images/blankpage.png diff --git a/.travis.yml b/.travis.yml index d7d39749..2ca5238d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,7 +8,7 @@ before_install: - sudo apt-get install libpng12-dev libwebp-dev libtiff4-dev libxml2-dev - sudo apt-get install swig libmagick++-dev bc - sudo apt-get install libcfitsio3-dev libgsl0-dev libmatio-dev - - sudo apt-get install liborc-0.4-dev liblcms2-dev + - sudo apt-get install liborc-0.4-dev liblcms2-dev libpoppler-glib-dev before_script: - ./bootstrap.sh - ./configure diff --git a/configure.ac b/configure.ac index 4ddb37fe..7aecb252 100644 --- a/configure.ac +++ b/configure.ac @@ -563,12 +563,12 @@ AC_ARG_WITH([poppler], AS_HELP_STRING([--without-poppler], [build without poppler (default: test)])) if test x"$with_poppler" != x"no"; then - PKG_CHECK_MODULES(POPPLER, [poppler-glib >= 0.30.0 cairo >= 1.2], - [AC_DEFINE(HAVE_POPPLER,1,[define if you have poppler-glib >= 0.30.0 and cairo >= 1.2 installed.]) + PKG_CHECK_MODULES(POPPLER, [poppler-glib >= 0.16.0 cairo >= 1.2], + [AC_DEFINE(HAVE_POPPLER,1,[define if you have poppler-glib >= 0.16.0 and cairo >= 1.2 installed.]) with_poppler=yes PACKAGES_USED="$PACKAGES_USED poppler-glib cairo" ], - [AC_MSG_WARN([poppler-glib >= 0.30.0 or cairo >= 1.2 not found; disabling PDF load via poppler]) + [AC_MSG_WARN([poppler-glib >= 0.16.0 or cairo >= 1.2 not found; disabling PDF load via poppler]) with_poppler=no ] ) @@ -961,7 +961,7 @@ file import with OpenSlide: $with_openslide (requires openslide-3.3.0 or later) file import with matio: $with_matio PDF import with poppler-glib: $with_poppler - (requires poppler-glib 0.30.0 or later) + (requires poppler-glib 0.16.0 or later) SVG import with librsvg-2.0: $with_rsvg (requires librsvg-2.0 2.40.0 or later) file import with cfitsio: $with_cfitsio diff --git a/test/images/blankpage.pdf b/test/images/blankpage.pdf new file mode 100755 index 00000000..5884469c --- /dev/null +++ b/test/images/blankpage.pdf @@ -0,0 +1,37 @@ +%PDF-1.1 +%âãÏÓ +1 0 obj +<< +/Pages 2 0 R +/Type /Catalog +>> +endobj +2 0 obj +<< +/MediaBox [0 0 595 842] +/Kids [3 0 R] +/Count 1 +/Type /Pages +>> +endobj +3 0 obj +<< +/Parent 2 0 R +/MediaBox [0 0 595 842] +/Type /Page +>> +endobj xref +0 4 +0000000000 65535 f +0000000015 00000 n +0000000066 00000 n +0000000149 00000 n +trailer + +<< +/Root 1 0 R +/Size 4 +>> +startxref +221 +%%EOF diff --git a/test/images/blankpage.png b/test/images/blankpage.png new file mode 100644 index 0000000000000000000000000000000000000000..00478276b6c929424245b9540189366b020172a3 GIT binary patch literal 3795 zcmeAS@N?(olHy`uVBq!ia0y~yUl5RScXGVsCl)HQk3>7nHGBI$R z5n*shSOzrQn3X|bh9*P90Ut&NmNYH~1p}aUjiX9N!(}uvjAoM2l3}zs9IYls>&DRr t!DvHiv~@VzY98$>jP{T4^cxSd^|f?V9|6c$A literal 0 HcmV?d00001 diff --git a/test/test_formats.sh b/test/test_formats.sh index 72af1ad4..bce44af1 100755 --- a/test/test_formats.sh +++ b/test/test_formats.sh @@ -7,6 +7,10 @@ . ./variables.sh +# poppler / pdfload reference image +poppler=$test_images/blankpage.pdf +poppler_ref=$test_images/blankpage.png + # the matlab image and reference image matlab=$test_images/sample.mat matlab_ref=$test_images/sample.png @@ -215,6 +219,10 @@ test_rad $rad test_raw $mono test_raw $image +if test_supported pdfload; then + test_loader $poppler_ref $poppler pdfload +fi + if test_supported matload; then test_loader $matlab_ref $matlab matlab fi From 6418ab230757b36a831019972f24cfa6db54cbdd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20Bu=CC=88nemann?= Date: Sun, 8 May 2016 23:26:10 +0200 Subject: [PATCH 23/34] Extract shared pdfload/svgload code into cairo.c --- libvips/foreign/Makefile.am | 1 + libvips/foreign/cairo.c | 68 +++++++++++++++++++++++++++++++++++++ libvips/foreign/svgload.c | 28 --------------- 3 files changed, 69 insertions(+), 28 deletions(-) create mode 100644 libvips/foreign/cairo.c diff --git a/libvips/foreign/Makefile.am b/libvips/foreign/Makefile.am index 004ba7f4..f1ccb01e 100644 --- a/libvips/foreign/Makefile.am +++ b/libvips/foreign/Makefile.am @@ -2,6 +2,7 @@ noinst_LTLIBRARIES = libforeign.la libforeign_la_SOURCES = \ gifload.c \ + cairo.c \ pdfload.c \ svgload.c \ radiance.h \ diff --git a/libvips/foreign/cairo.c b/libvips/foreign/cairo.c new file mode 100644 index 00000000..f8f6dec5 --- /dev/null +++ b/libvips/foreign/cairo.c @@ -0,0 +1,68 @@ +/* Shared code for cairo based loaders like svgload and pdfload. + */ + +/* + + This file is part of VIPS. + + VIPS is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301 USA + + */ + +/* + + These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk + + */ + +#ifdef HAVE_CONFIG_H +#include +#endif /*HAVE_CONFIG_H*/ + +#if defined(HAVE_RSVG) || defined(HAVE_POPPLER) + +#include +#include + +/* Convert from ARGB to RGBA and undo premultiplication. + */ +void +vips__cairo2rgba( guint32 * restrict buf, int n ) +{ + int i; + + for( i = 0; i < n; i++ ) { + guint32 * restrict p = buf + i; + guint32 x = *p; + guint8 a = x >> 24; + VipsPel * restrict out = (VipsPel *) p; + + if( a == 255 ) + *p = GUINT32_TO_BE( (x << 8) | 255 ); + else if( a == 0 ) + *p = GUINT32_TO_BE( x << 8 ); + else { + /* Undo premultiplication. + */ + out[0] = 255 * ((x >> 16) & 255) / a; + out[1] = 255 * ((x >> 8) & 255) / a; + out[2] = 255 * (x & 255) / a; + out[3] = a; + } + } +} + +#endif diff --git a/libvips/foreign/svgload.c b/libvips/foreign/svgload.c index 929b7a64..7b41e31a 100644 --- a/libvips/foreign/svgload.c +++ b/libvips/foreign/svgload.c @@ -149,34 +149,6 @@ vips_foreign_load_svg_header( VipsForeignLoad *load ) return( 0 ); } -/* Convert from ARGB to RGBA and undo premultiplication. - */ -void -vips__cairo2rgba( guint32 * restrict buf, int n ) -{ - int i; - - for( i = 0; i < n; i++ ) { - guint32 * restrict p = buf + i; - guint32 x = *p; - guint8 a = x >> 24; - VipsPel * restrict out = (VipsPel *) p; - - if( a == 255 ) - *p = GUINT32_TO_BE( (x << 8) | 255 ); - else if( a == 0 ) - *p = GUINT32_TO_BE( x << 8 ); - else { - /* Undo premultiplication. - */ - out[0] = 255 * ((x >> 16) & 255) / a; - out[1] = 255 * ((x >> 8) & 255) / a; - out[2] = 255 * (x & 255) / a; - out[3] = a; - } - } -} - static int vips_foreign_load_svg_generate( VipsRegion *or, void *seq, void *a, void *b, gboolean *stop ) From 8b3bb10b00e0cbfdd59dd70045c916a989ef1fcb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20Bu=CC=88nemann?= Date: Mon, 9 May 2016 00:48:37 +0200 Subject: [PATCH 24/34] Fix test_{threading,thumbnail}.sh without install Both scripts were not using the $vips variables required to use vips from the source directory instead of from the system. --- test/test_threading.sh | 12 ++++++------ test/test_thumbnail.sh | 26 +++++++++++++------------- 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/test/test_threading.sh b/test/test_threading.sh index ec335335..a7e7beb2 100755 --- a/test/test_threading.sh +++ b/test/test_threading.sh @@ -7,22 +7,22 @@ chain=1 # im_benchmark needs a labq -vips colourspace $image $tmp/t3.v labq +$vips colourspace $image $tmp/t3.v labq for tile in 10 64 128 512; do # benchmark includes a dither which will vary with tile size - vips --vips-concurrency=1 \ + $vips --vips-concurrency=1 \ --vips-tile-width=$tile --vips-tile-height=$tile \ im_benchmarkn $tmp/t3.v $tmp/t5.v $chain for cpus in 2 3 4 5 6 7 8 99; do echo trying cpus = $cpus, tile = $tile ... - vips --vips-concurrency=$cpus \ + $vips --vips-concurrency=$cpus \ --vips-tile-width=$tile --vips-tile-height=$tile \ im_benchmarkn $tmp/t3.v $tmp/t7.v $chain - vips subtract $tmp/t5.v $tmp/t7.v $tmp/t8.v - vips abs $tmp/t8.v $tmp/t9.v - max=$(vips max $tmp/t9.v) + $vips subtract $tmp/t5.v $tmp/t7.v $tmp/t8.v + $vips abs $tmp/t8.v $tmp/t9.v + max=$($vips max $tmp/t9.v) if [ $(echo "$max > 0" | bc) -eq 1 ]; then break fi diff --git a/test/test_thumbnail.sh b/test/test_thumbnail.sh index 5044d0a0..73912e8c 100755 --- a/test/test_thumbnail.sh +++ b/test/test_thumbnail.sh @@ -11,10 +11,10 @@ # make a 1000x1000 mono test image ... add a bit so the image should not # contain any zeros, helps to spot missing tiles and bad pixels echo building test image ... -vips extract_band $image $tmp/t1.v 1 -vips linear $tmp/t1.v $tmp/t2.v 1 20 --uchar -vips replicate $tmp/t2.v $tmp/t1.v 2 2 -vips crop $tmp/t1.v $tmp/t2.v 10 10 1000 1000 +$vips extract_band $image $tmp/t1.v 1 +$vips linear $tmp/t1.v $tmp/t2.v 1 20 --uchar +$vips replicate $tmp/t2.v $tmp/t1.v 2 2 +$vips crop $tmp/t1.v $tmp/t2.v 10 10 1000 1000 # is a difference beyond a threshold? return 0 (meaning all ok) or 1 (meaning # error, or outside threshold) @@ -27,33 +27,33 @@ break_threshold() { size=1000 while [ $size -gt 99 ]; do printf "testing size to $size ... " - vipsthumbnail $tmp/t2.v -o $tmp/t1.v --size $size - if [ $(vipsheader -f width $tmp/t1.v) -ne $size ]; then + $vipsthumbnail $tmp/t2.v -o $tmp/t1.v --size $size + if [ $($vipsheader -f width $tmp/t1.v) -ne $size ]; then echo $tmp/t1.v failed -- bad size - echo output width is $(vipsheader -f width $tmp/t1.v) + echo output width is $($vipsheader -f width $tmp/t1.v) exit fi - if [ $(vipsheader -f height $tmp/t1.v) -ne $size ]; then + if [ $($vipsheader -f height $tmp/t1.v) -ne $size ]; then echo $tmp/t1.v failed -- bad size - echo output height is $(vipsheader -f width $tmp/t1.v) + echo output height is $($vipsheader -f width $tmp/t1.v) exit fi - vips project $tmp/t1.v $tmp/cols.v $tmp/rows.v + $vips project $tmp/t1.v $tmp/cols.v $tmp/rows.v - min=$(vips min $tmp/cols.v) + min=$($vips min $tmp/cols.v) if break_threshold $min 0; then echo $tmp/t1.v failed -- has a black column exit fi - min=$(vips min $tmp/rows.v) + min=$($vips min $tmp/rows.v) if break_threshold $min 0; then echo $tmp/t1.v failed -- has a black row exit fi - min=$(vips min $tmp/t1.v) + min=$($vips min $tmp/t1.v) if break_threshold $min 0; then echo $tmp/t1.v failed -- has black pixels exit From d307e38863af84f91fbfd83c05ac54a8cbf556aa Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Mon, 9 May 2016 09:51:05 +0100 Subject: [PATCH 25/34] add FIND_LIBWEBP some platforms are missing a .pc file for libwebp ... add a FIND_LIBWEBP macro as a fallback see https://github.com/jcupitt/libvips/issues/440 --- acinclude.m4 | 120 +++++++++++++++++++++++++++++++++++++++++++++++++++ configure.ac | 13 ++++-- 2 files changed, 130 insertions(+), 3 deletions(-) diff --git a/acinclude.m4 b/acinclude.m4 index d1bbc58f..3e260465 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -684,3 +684,123 @@ fi ])dnl + +dnl From FIND_MOTIF and ACX_PTHREAD, without much understanding +dnl +dnl FIND_LIBWEBP[ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]] +dnl --------------------------------------------------- +dnl +dnl Find webp libraries and headers ... useful for platforms which are missing +dnl the webp .pc file +dnl +dnl Put compile stuff in LIBWEBP_INCLUDES +dnl Put link stuff in LIBWEBP_LIBS +dnl Define HAVE_LIBWEBP if found. +dnl +AC_DEFUN([FIND_LIBWEBP], [ +AC_REQUIRE([AC_PATH_XTRA]) + +LIBWEBP_INCLUDES="" +LIBWEBP_LIBS="" + +AC_ARG_WITH(libwebp, + AS_HELP_STRING([--without-libwebp], [build without libwebp (default: test)])) +# Treat --without-libwebp like --without-libwebp-includes --without-libwebp-libraries. +if test "$with_libwebp" = "no"; then + LIBWEBP_INCLUDES=no + LIBWEBP_LIBS=no +fi + +AC_ARG_WITH(libwebp-includes, + AS_HELP_STRING([--with-libwebp-includes=DIR], [libwebp includes are in DIR]), + LIBWEBP_INCLUDES="-I$withval") +AC_ARG_WITH(libwebp-libraries, + AS_HELP_STRING([--with-libwebp-libraries=DIR], [libwebp libraries are in DIR]), + LIBWEBP_LIBS="-L$withval -lwebp") + +AC_MSG_CHECKING(for libwebp) + +# Look for webp/decode.h +if test "$LIBWEBP_INCLUDES" = ""; then + # Check the standard search path + AC_TRY_COMPILE([#include ],[int a;],[ + LIBWEBP_INCLUDES="" + ], [ + # webp/decode.h is not in the standard search path, try + # $prefix + libwebp_save_INCLUDES="$INCLUDES" + + INCLUDES="-I${prefix}/include $INCLUDES" + + AC_TRY_COMPILE([#include ],[int a;],[ + LIBWEBP_INCLUDES="-I${prefix}/include" + ], [ + LIBWEBP_INCLUDES="no" + ]) + + INCLUDES=$libwebp_save_INCLUDES + ]) +fi + +# Now for the libraries +if test "$LIBWEBP_LIBS" = ""; then + libwebp_save_LIBS="$LIBS" + libwebp_save_INCLUDES="$INCLUDES" + + LIBS="-lwebp $LIBS" + INCLUDES="$LIBWEBP_INCLUDES $INCLUDES" + + # Try the standard search path first + AC_TRY_LINK([#include ],[WebPInitDecoderConfig(0)], [ + LIBWEBP_LIBS="-lwebp" + ], [ + # libwebp is not in the standard search path, try $prefix + + LIBS="-L${prefix}/lib $LIBS" + + AC_TRY_LINK([#include ],[WebPInitDecoderConfig(0)], [ + LIBWEBP_LIBS="-L${prefix}/lib -lwebp" + ], [ + LIBWEBP_LIBS=no + ]) + ]) + + LIBS="$libwebp_save_LIBS" + INCLUDES="$libwebp_save_INCLUDES" +fi + +AC_SUBST(LIBWEBP_LIBS) +AC_SUBST(LIBWEBP_INCLUDES) + +# Print a helpful message +libwebp_libraries_result="$LIBWEBP_LIBS" +libwebp_includes_result="$LIBWEBP_INCLUDES" + +if test x"$libwebp_libraries_result" = x""; then + libwebp_libraries_result="in default path" +fi +if test x"$libwebp_includes_result" = x""; then + libwebp_includes_result="in default path" +fi + +if test "$libwebp_libraries_result" = "no"; then + libwebp_libraries_result="(none)" +fi +if test "$libwebp_includes_result" = "no"; then + libwebp_includes_result="(none)" +fi + +AC_MSG_RESULT([libraries $libwebp_libraries_result, headers $libwebp_includes_result]) + +# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND: +if test "$LIBWEBP_INCLUDES" != "no" && test "$LIBWEBP_LIBS" != "no"; then + AC_DEFINE(HAVE_LIBWEBP,1,[Define if you have libwebp libraries and header files.]) + $1 +else + LIBWEBP_INCLUDES="" + LIBWEBP_LIBS="" + $2 +fi + +])dnl + diff --git a/configure.ac b/configure.ac index 4ddb37fe..8bbe6492 100644 --- a/configure.ac +++ b/configure.ac @@ -673,6 +673,8 @@ if test x"$with_cfitsio" != "xno"; then fi # libwebp +# some platforms, like ubuntu 12.04, are missing the .pc files for libwebp, so +# we fall back to FIND_LIBWEBP AC_ARG_WITH([libwebp], AS_HELP_STRING([--without-libwebp], [build without libwebp (default: test)])) @@ -681,9 +683,14 @@ if test x"$with_libwebp" != "xno"; then [AC_DEFINE(HAVE_LIBWEBP,1,[define if you have libwebp installed.]) with_libwebp=yes PACKAGES_USED="$PACKAGES_USED libwebp"], - [AC_MSG_WARN([libwebp not found; disabling libwebp support]) - with_libwebp=no - ]) + [FIND_LIBWEBP([ + with_libwebp="yes (found by search)" + ], [ + AC_MSG_WARN([libwebp not found; disabling WEBP support]) + with_libwebp=no + ]) + ] + ) fi # pangoft2 From bab11cec1d40be38151e34262f107359a94e2730 Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Mon, 9 May 2016 10:44:32 +0100 Subject: [PATCH 26/34] always build cairo.c --- libvips/foreign/cairo.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/libvips/foreign/cairo.c b/libvips/foreign/cairo.c index f8f6dec5..b242ab49 100644 --- a/libvips/foreign/cairo.c +++ b/libvips/foreign/cairo.c @@ -32,12 +32,12 @@ #include #endif /*HAVE_CONFIG_H*/ -#if defined(HAVE_RSVG) || defined(HAVE_POPPLER) - #include #include /* Convert from ARGB to RGBA and undo premultiplication. + * + * See also openslide's argb2rgba(). */ void vips__cairo2rgba( guint32 * restrict buf, int n ) @@ -64,5 +64,3 @@ vips__cairo2rgba( guint32 * restrict buf, int n ) } } } - -#endif From 143593d6a6b157b439813245d2e939be72d73287 Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Mon, 9 May 2016 11:07:48 +0100 Subject: [PATCH 27/34] comment reformat --- ChangeLog | 1 + libvips/foreign/foreign.c | 21 ++++++++++++--------- libvips/foreign/vips2jpeg.c | 2 ++ 3 files changed, 15 insertions(+), 9 deletions(-) diff --git a/ChangeLog b/ChangeLog index e16f8162..02a3eb77 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,6 @@ 1/5/16 started 8.4 - many more wepsave options [Felix Bünemann] +- added quant_table option to wepsave [Felix Bünemann] 15/4/16 started 8.3.1 - rename vips wrapper script, it was still vips-8.2, thanks Benjamin diff --git a/libvips/foreign/foreign.c b/libvips/foreign/foreign.c index 10fb231c..78b8ea76 100644 --- a/libvips/foreign/foreign.c +++ b/libvips/foreign/foreign.c @@ -2272,15 +2272,18 @@ vips_jpegload_buffer( void *buf, size_t len, VipsImage **out, ... ) * If @quant_table is set and the version of libjpeg supports it * (e.g. mozjpeg >= 3.0) it selects the quantization table to use: * - * * 0 Tables from JPEG Annex K (vips and libjpeg default) - * * 1 Flat table - * * 2 Table tuned for MSSIM on Kodak image set - * * 3 Table from ImageMagick by N. Robidoux (current mozjpeg default) - * * 4 Table tuned for PSNR-HVS-M on Kodak image set - * * 5 Table from Relevance of Human Vision to JPEG-DCT Compression (1992) - * * 6 Table from DCTune Perceptual Optimization of Compressed Dental X-Rays (1997) - * * 7 Table from A Visual Detection Model for DCT Coefficient Quantization (1993) - * * 8 Table from An Improved Detection Model for DCT Coefficient Quantization (1993) + * * 0 — Tables from JPEG Annex K (vips and libjpeg default) + * * 1 — Flat table + * * 2 — Table tuned for MSSIM on Kodak image set + * * 3 — Table from ImageMagick by N. Robidoux (current mozjpeg default) + * * 4 — Table tuned for PSNR-HVS-M on Kodak image set + * * 5 — Table from Relevance of Human Vision to JPEG-DCT Compression (1992) + * * 6 — Table from DCTune Perceptual Optimization of Compressed Dental + * X-Rays (1997) + * * 7 — Table from A Visual Detection Model for DCT Coefficient + * Quantization (1993) + * * 8 — Table from An Improved Detection Model for DCT Coefficient + * Quantization (1993) * * Quantization table 0 is the default in vips and libjpeg(-turbo), but it * tends to favor detail over color accuracy, producting colored patches and diff --git a/libvips/foreign/vips2jpeg.c b/libvips/foreign/vips2jpeg.c index 0c7bda5b..0f60a9ef 100644 --- a/libvips/foreign/vips2jpeg.c +++ b/libvips/foreign/vips2jpeg.c @@ -74,6 +74,8 @@ * - don't write JFIF headers if we are stripping, thanks Benjamin * 13/4/16 * - remove deleted exif fields more carefully + * 9/5/16 felixbuenemann + * - add quant_table */ /* From 4640aab38825de8536e24b16d5c86961cc895da6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20Bu=CC=88nemann?= Date: Mon, 9 May 2016 12:29:23 +0200 Subject: [PATCH 28/34] Test against system libwebp on Travis CI * Dropped custom ppa used only for libwebp backport * Dropped lossless test from `make check` (not supported in 0.1.3) --- .travis.yml | 1 - test/test_formats.sh | 1 - 2 files changed, 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 2ca5238d..3852c822 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,5 @@ language: cpp before_install: - - sudo add-apt-repository ppa:lyrasis/precise-backports -y - sudo apt-get update -qq - sudo apt-get install automake gtk-doc-tools - sudo apt-get install gobject-introspection diff --git a/test/test_formats.sh b/test/test_formats.sh index bce44af1..c44ce02e 100755 --- a/test/test_formats.sh +++ b/test/test_formats.sh @@ -192,7 +192,6 @@ if test_supported jpegload; then fi if test_supported webpload; then test_format $image webp 90 - test_format $image webp 0 [lossless] fi test_format $image ppm 0 test_format $image pfm 0 From 3b7242f74355119acc32a27b760294046c74787d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20Bu=CC=88nemann?= Date: Mon, 9 May 2016 13:08:11 +0200 Subject: [PATCH 29/34] Fix webpsave alpha_q default value --- libvips/foreign/webpsave.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libvips/foreign/webpsave.c b/libvips/foreign/webpsave.c index f677ff0e..77e65108 100644 --- a/libvips/foreign/webpsave.c +++ b/libvips/foreign/webpsave.c @@ -160,6 +160,7 @@ static void vips_foreign_save_webp_init( VipsForeignSaveWebp *webp ) { webp->Q = 75; + webp->alpha_q = 100; } typedef struct _VipsForeignSaveWebpFile { From 9db05c30c2629c06a21a642ad47d362599cf6e93 Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Mon, 9 May 2016 14:06:44 +0100 Subject: [PATCH 30/34] tiny README fixes --- README.md | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 3f5112e9..fed316b3 100644 --- a/README.md +++ b/README.md @@ -150,12 +150,14 @@ libraries automatically. See `./configure --help` for a set of flags to control library detection. Packages are generally found with `pkg-config`, so make sure that is working. -libtiff and libjpeg do not usually use `pkg-config` so libvips looks for +libtiff, giflib and libjpeg do not usually use `pkg-config` so libvips looks for them in the default path and in `$prefix`. If you have installed your own versions of these libraries in a different location, libvips will not see them. Use switches to libvips configure like: ./configure --prefix=/Users/john/vips \ + --with-giflib-includes=/opt/local/include \ + --with-giflib-libraries=/opt/local/lib \ --with-tiff-includes=/opt/local/include \ --with-tiff-libraries=/opt/local/lib \ --with-jpeg-includes=/opt/local/include \ @@ -187,8 +189,6 @@ If available, libvips adds support for EXIF metadata in JPEG files. The standard gif loader. If this is not present, vips will try to load gifs via imagemagick instead. -vips will only work with giflib 4. - ### librsvg The usual SVG loader. If this is not present, vips will try to load SVGs @@ -238,6 +238,11 @@ Imagemagick 6.9+ needs to have been built with `--with-modules`. Most packaged IMs are, I think, but if you are rolling your own, you'll need to pass this flag to configure. +If you are going to be using libvips with untrusted images, perhaps in a +web-server, for example, you should consider the security implications of +using a package with such a large attack surface. You might prefer not to +enable Magick support. + ### pangoft2 If available, libvips adds support for text rendering. You need the From cb97d3d7868e13afa7fb1c5e3818e34e11bddd0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20Bu=CC=88nemann?= Date: Mon, 9 May 2016 18:37:00 +0200 Subject: [PATCH 31/34] Remove jpegsave default quant_table debug print This was only ut in for debugging which quant_table is used in the JCP_FASTEST profile and should've never been committed. --- libvips/foreign/vips2jpeg.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/libvips/foreign/vips2jpeg.c b/libvips/foreign/vips2jpeg.c index 0f60a9ef..1345bae8 100644 --- a/libvips/foreign/vips2jpeg.c +++ b/libvips/foreign/vips2jpeg.c @@ -1090,8 +1090,6 @@ write_vips( Write *write, int qfac, const char *profile, vips_warn( "vips2jpeg", "%s", _( "Setting quant_table unsupported" ) ); } - vips_warn( "vips2jpeg", "quant_table %d", - jpeg_c_get_int_param( &write->cinfo, JINT_BASE_QUANT_TBL_IDX ) ); #else /* Using jpeglib.h without extension parameters, warn of ignored * options. From 9fba3b55770a976f54f06eff0ed17b238717b905 Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Thu, 12 May 2016 08:55:19 +0100 Subject: [PATCH 32/34] notes on TODO --- TODO | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/TODO b/TODO index ebbd8c6d..d8dfc955 100644 --- a/TODO +++ b/TODO @@ -1,3 +1,10 @@ +- this seems to not work: + + $ vips copy k2.jpg x.dz[suffix=.jpg[Q=90]] + dzsave: not , or ) after parameter + +- add n_pages to pdfload + - add more webp tests to py suite - the gif tests in the suite sometimes fail with giflib5 because of an From 24a51098b178b67eb8051d04cb1cdcfa365d8af8 Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Thu, 12 May 2016 14:54:28 +0100 Subject: [PATCH 33/34] compiler warning --- TODO | 2 -- libvips/iofuncs/header.c | 15 ++++++++------- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/TODO b/TODO index d8dfc955..cd1ab676 100644 --- a/TODO +++ b/TODO @@ -3,8 +3,6 @@ $ vips copy k2.jpg x.dz[suffix=.jpg[Q=90]] dzsave: not , or ) after parameter -- add n_pages to pdfload - - add more webp tests to py suite - the gif tests in the suite sometimes fail with giflib5 because of an diff --git a/libvips/iofuncs/header.c b/libvips/iofuncs/header.c index 5e913759..61d5b177 100644 --- a/libvips/iofuncs/header.c +++ b/libvips/iofuncs/header.c @@ -433,10 +433,10 @@ vips_image_guess_format( const VipsImage *image ) break; case VIPS_INTERPRETATION_CMYK: - if( image->BandFmt != VIPS_FORMAT_USHORT ) - format = VIPS_FORMAT_UCHAR; + if( image->BandFmt == VIPS_FORMAT_USHORT ) + format = VIPS_FORMAT_USHORT; else - format = image->BandFmt; + format = VIPS_FORMAT_UCHAR; break; case VIPS_INTERPRETATION_LABQ: @@ -453,14 +453,15 @@ vips_image_guess_format( const VipsImage *image ) break; case VIPS_INTERPRETATION_MATRIX: - if( image->BandFmt != VIPS_FORMAT_DOUBLE ) - format = VIPS_FORMAT_FLOAT; + if( image->BandFmt == VIPS_FORMAT_DOUBLE ) + format = VIPS_FORMAT_DOUBLE; else - format = image->BandFmt; + format = VIPS_FORMAT_FLOAT; break; default: - g_assert_not_reached(); + format = VIPS_FORMAT_NOTSET; + break; } return( format ); From 2cfe4842d3b16470f10504e475a2a41abf42e66d Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Sun, 15 May 2016 09:48:02 +0100 Subject: [PATCH 34/34] notes --- TODO | 2 ++ 1 file changed, 2 insertions(+) diff --git a/TODO b/TODO index cd1ab676..6692c7f0 100644 --- a/TODO +++ b/TODO @@ -5,6 +5,8 @@ - add more webp tests to py suite +- try moving some more of the CLI tests to py + - the gif tests in the suite sometimes fail with giflib5 because of an uninitialized struct in giflib, see