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 );
 }