diff --git a/ChangeLog b/ChangeLog index 5cd95dc8..52e1e299 100644 --- a/ChangeLog +++ b/ChangeLog @@ -37,6 +37,7 @@ - dzsave to szi will write all associated images - remove old c++ and python interfaces - vipsthumbnail can thumbnail animated and multipage images +- deprecate webpload @shrink, use @scale instead 31/3/19 started 8.7.5 - better buffer sizing in tiff reader [omira-sch] diff --git a/libvips/foreign/pforeign.h b/libvips/foreign/pforeign.h index cee9102a..0f2c304f 100644 --- a/libvips/foreign/pforeign.h +++ b/libvips/foreign/pforeign.h @@ -226,14 +226,14 @@ int vips__iswebp_buffer( const void *buf, size_t len ); int vips__iswebp( const char *filename ); int vips__webp_read_file_header( const char *name, VipsImage *out, - int page, int n, int shrink ); + int page, int n, double scale ); int vips__webp_read_file( const char *name, VipsImage *out, - int page, int n, int shrink ); + int page, int n, double scale ); int vips__webp_read_buffer_header( const void *buf, size_t len, VipsImage *out, - int page, int n, int shrink ); + int page, int n, double scale ); int vips__webp_read_buffer( const void *buf, size_t len, VipsImage *out, - int page, int n, int shrink ); + int page, int n, double scale ); int vips__webp_write_file( VipsImage *out, const char *filename, int Q, gboolean lossless, VipsForeignWebpPreset preset, diff --git a/libvips/foreign/webp2vips.c b/libvips/foreign/webp2vips.c index 5bb3e20c..0faf3b57 100644 --- a/libvips/foreign/webp2vips.c +++ b/libvips/foreign/webp2vips.c @@ -17,6 +17,9 @@ * - could memleak on some read errors * 24/4/19 * - fix bg handling in animations + * 30/4/19 + * - deprecate shrink, use scale instead, and make it a double ... this + * lets us do faster and more accurate thumbnailing */ /* @@ -90,9 +93,9 @@ typedef struct { */ int n; - /* Shrink-on-load factor. Use this to set scaled_width. + /* Scale-on-load factor. Use this to set scaled_width. */ - int shrink; + double scale; /* Size of final output image. */ @@ -325,7 +328,7 @@ read_free( Read *read ) static Read * read_new( const char *filename, const void *data, size_t length, - int page, int n, int shrink ) + int page, int n, double scale ) { Read *read; @@ -337,7 +340,7 @@ read_new( const char *filename, const void *data, size_t length, read->length = length; read->page = page; read->n = n; - read->shrink = shrink; + read->scale = scale; read->delay = 100; read->fd = 0; read->demux = NULL; @@ -394,10 +397,12 @@ read_header( Read *read, VipsImage *out ) canvas_width = WebPDemuxGetI( read->demux, WEBP_FF_CANVAS_WIDTH ); canvas_height = WebPDemuxGetI( read->demux, WEBP_FF_CANVAS_HEIGHT ); - read->frame_width = canvas_width / read->shrink; - read->frame_height = canvas_height / read->shrink; + /* We round-to-nearest cf. pdfload etc. + */ + read->frame_width = VIPS_RINT( canvas_width * read->scale ); + read->frame_height = VIPS_RINT( canvas_height * read->scale ); - if( read->shrink > 1 ) { + if( read->scale != 1.0 ) { read->config.options.use_scaling = 1; read->config.options.scaled_width = read->frame_width; read->config.options.scaled_height = read->frame_height; @@ -521,11 +526,11 @@ read_header( Read *read, VipsImage *out ) int vips__webp_read_file_header( const char *filename, VipsImage *out, - int page, int n, int shrink ) + int page, int n, double scale ) { Read *read; - if( !(read = read_new( filename, NULL, 0, page, n, shrink )) ) { + if( !(read = read_new( filename, NULL, 0, page, n, scale )) ) { vips_error( "webp2vips", _( "unable to open \"%s\"" ), filename ); return( -1 ); @@ -606,10 +611,10 @@ read_next_frame( Read *read ) /* Note this frame's dispose for next time. */ read->dispose_method = read->iter.dispose_method; - read->dispose_rect.left = read->iter.x_offset; - read->dispose_rect.top = read->iter.y_offset; - read->dispose_rect.width = read->iter.width; - read->dispose_rect.height = read->iter.height; + read->dispose_rect.left = read->iter.x_offset * read->scale; + read->dispose_rect.top = read->iter.y_offset * read->scale; + read->dispose_rect.width = read->iter.width * read->scale; + read->dispose_rect.height = read->iter.height * read->scale; #ifdef DEBUG printf( "webp2vips: frame_num = %d\n", read->iter.frame_num ); @@ -715,11 +720,11 @@ read_image( Read *read, VipsImage *out ) int vips__webp_read_file( const char *filename, VipsImage *out, - int page, int n, int shrink ) + int page, int n, double scale ) { Read *read; - if( !(read = read_new( filename, NULL, 0, page, n, shrink )) ) { + if( !(read = read_new( filename, NULL, 0, page, n, scale )) ) { vips_error( "webp2vips", _( "unable to open \"%s\"" ), filename ); return( -1 ); @@ -737,11 +742,11 @@ vips__webp_read_file( const char *filename, VipsImage *out, int vips__webp_read_buffer_header( const void *buf, size_t len, VipsImage *out, - int page, int n, int shrink ) + int page, int n, double scale ) { Read *read; - if( !(read = read_new( NULL, buf, len, page, n, shrink )) ) { + if( !(read = read_new( NULL, buf, len, page, n, scale )) ) { vips_error( "webp2vips", "%s", _( "unable to open buffer" ) ); return( -1 ); @@ -759,11 +764,11 @@ vips__webp_read_buffer_header( const void *buf, size_t len, VipsImage *out, int vips__webp_read_buffer( const void *buf, size_t len, VipsImage *out, - int page, int n, int shrink ) + int page, int n, double scale ) { Read *read; - if( !(read = read_new( NULL, buf, len, page, n, shrink )) ) { + if( !(read = read_new( NULL, buf, len, page, n, scale )) ) { vips_error( "webp2vips", "%s", _( "unable to open buffer" ) ); return( -1 ); diff --git a/libvips/foreign/webpload.c b/libvips/foreign/webpload.c index 367dbd72..545fc793 100644 --- a/libvips/foreign/webpload.c +++ b/libvips/foreign/webpload.c @@ -6,6 +6,8 @@ * - add @shrink * 1/11/18 * - add @page, @n + * 30/4/19 + * - deprecate @shrink, use @scale instead */ /* @@ -64,9 +66,13 @@ typedef struct _VipsForeignLoadWebp { */ int n; - /* Shrink by this much during load. + /* Scale by this much during load. */ - int shrink; + double scale; + + /* Old and deprecated scaling path. + */ + int shrink; } VipsForeignLoadWebp; typedef VipsForeignLoadClass VipsForeignLoadWebpClass; @@ -120,10 +126,20 @@ vips_foreign_load_webp_class_init( VipsForeignLoadWebpClass *class ) G_STRUCT_OFFSET( VipsForeignLoadWebp, n ), -1, 100000, 1 ); - VIPS_ARG_INT( class, "shrink", 22, + VIPS_ARG_DOUBLE( class, "scale", 22, + _( "Scale" ), + _( "Scale factor on load" ), + VIPS_ARGUMENT_OPTIONAL_INPUT, + G_STRUCT_OFFSET( VipsForeignLoadWebp, scale ), + 0.0, 1024.0, 1.0 ); + + /* Old and deprecated scaling API. A float param lets do + * shrink-on-load for thumbnail faster and more accurately. + */ + VIPS_ARG_INT( class, "shrink", 23, _( "Shrink" ), _( "Shrink factor on load" ), - VIPS_ARGUMENT_OPTIONAL_INPUT, + VIPS_ARGUMENT_OPTIONAL_INPUT | VIPS_ARGUMENT_DEPRECATED, G_STRUCT_OFFSET( VipsForeignLoadWebp, shrink ), 1, 1024, 1 ); @@ -134,6 +150,7 @@ vips_foreign_load_webp_init( VipsForeignLoadWebp *webp ) { webp->n = 1; webp->shrink = 1; + webp->scale = 1.0; } typedef struct _VipsForeignLoadWebpFile { @@ -168,8 +185,15 @@ vips_foreign_load_webp_file_header( VipsForeignLoad *load ) VipsForeignLoadWebp *webp = (VipsForeignLoadWebp *) load; VipsForeignLoadWebpFile *file = (VipsForeignLoadWebpFile *) load; + /* BC for the old API. + */ + if( !vips_object_argument_isset( VIPS_OBJECT( load ), "scale" ) && + vips_object_argument_isset( VIPS_OBJECT( load ), "shrink" ) && + webp->shrink != 0 ) + webp->scale = 1.0 / webp->shrink; + if( vips__webp_read_file_header( file->filename, load->out, - webp->page, webp->n, webp->shrink ) ) + webp->page, webp->n, webp->scale ) ) return( -1 ); VIPS_SETSTR( load->out->filename, file->filename ); @@ -184,7 +208,7 @@ vips_foreign_load_webp_file_load( VipsForeignLoad *load ) VipsForeignLoadWebpFile *file = (VipsForeignLoadWebpFile *) load; if( vips__webp_read_file( file->filename, load->real, - webp->page, webp->n, webp->shrink ) ) + webp->page, webp->n, webp->scale ) ) return( -1 ); return( 0 ); @@ -249,7 +273,7 @@ vips_foreign_load_webp_buffer_header( VipsForeignLoad *load ) if( vips__webp_read_buffer_header( buffer->buf->data, buffer->buf->length, load->out, - webp->page, webp->n, webp->shrink ) ) + webp->page, webp->n, webp->scale ) ) return( -1 ); return( 0 ); @@ -263,7 +287,7 @@ vips_foreign_load_webp_buffer_load( VipsForeignLoad *load ) if( vips__webp_read_buffer( buffer->buf->data, buffer->buf->length, load->real, - webp->page, webp->n, webp->shrink ) ) + webp->page, webp->n, webp->scale ) ) return( -1 ); return( 0 ); @@ -317,7 +341,7 @@ vips_foreign_load_webp_buffer_init( VipsForeignLoadWebpBuffer *buffer ) * * * @page: %gint, page (frame) to read * * @n: %gint, load this many pages - * * @shrink: %gint, shrink by this much on load + * * @scale: %gdouble, scale by this much on load * * Read a WebP file into a VIPS image. * @@ -328,7 +352,8 @@ vips_foreign_load_webp_buffer_init( VipsForeignLoadWebpBuffer *buffer ) * left. Set to -1 to mean "until the end of the document". Use vips_grid() * to change page layout. * - * Use @shrink to specify a shrink-on-load factor. + * Use @scale to specify a scale-on-load factor. For example, 2.0 to double + * the size on load. * * The loader supports ICC, EXIF and XMP metadata. * @@ -360,7 +385,7 @@ vips_webpload( const char *filename, VipsImage **out, ... ) * * * @page: %gint, page (frame) to read * * @n: %gint, load this many pages - * * @shrink: %gint, shrink by this much on load + * * @scale: %gdouble, scale 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. diff --git a/libvips/resample/thumbnail.c b/libvips/resample/thumbnail.c index b6b96956..bb01e8c1 100644 --- a/libvips/resample/thumbnail.c +++ b/libvips/resample/thumbnail.c @@ -510,12 +510,12 @@ vips_thumbnail_open( VipsThumbnail *thumbnail ) } else if( vips_isprefix( "VipsForeignLoadWebp", thumbnail->loader ) ) { - factor = (int) VIPS_MAX( 1.0, + factor = 1.0 / vips_thumbnail_calculate_common_shrink( thumbnail, thumbnail->input_width, - thumbnail->page_height ) ); + thumbnail->page_height ); - g_info( "loading webp with factor %g pre-shrink", factor ); + g_info( "loading webp with factor %g pre-scale", factor ); } if( !(im = class->open( thumbnail, factor )) ) @@ -940,7 +940,7 @@ vips_thumbnail_file_open( VipsThumbnail *thumbnail, double factor ) vips_isprefix( "VipsForeignLoadWebp", thumbnail->loader ) ) { return( vips_image_new_from_file( file->filename, "access", VIPS_ACCESS_SEQUENTIAL, - "shrink", (int) factor, + "scale", factor, NULL ) ); } else if( vips_isprefix( "VipsForeignLoadOpenslide", @@ -1134,7 +1134,7 @@ vips_thumbnail_buffer_open( VipsThumbnail *thumbnail, double factor ) buffer->buf->data, buffer->buf->length, buffer->option_string, "access", VIPS_ACCESS_SEQUENTIAL, - "shrink", (int) factor, + "scale", factor, NULL ) ); } else if( vips_isprefix( "VipsForeignLoadOpenslide",