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
This commit is contained in:
Felix Bünemann 2016-04-23 07:00:42 +02:00
parent 0a25f6efca
commit 874cc8b31b
3 changed files with 95 additions and 19 deletions

View File

@ -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)

View File

@ -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.

View File

@ -46,6 +46,7 @@
#ifdef HAVE_LIBWEBP
#include <stdlib.h>
#include <string.h>
#include <vips/vips.h>
@ -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;
}