diff --git a/ChangeLog b/ChangeLog index 80c86ba1..8eca57e1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -20,6 +20,7 @@ - fix race in temp filename creation [lhecker] - add @reduction_effort param to webpsave [lovell] - add vips_heifload(), vips_heifsave() +- add heif thumbnail support to vips_thumbnail() 4/1/19 started 8.7.4 - magickload with magick6 API did not chain exceptions correctly causing a diff --git a/libvips/foreign/heifload.c b/libvips/foreign/heifload.c index 1c05dd2a..80615ee5 100644 --- a/libvips/foreign/heifload.c +++ b/libvips/foreign/heifload.c @@ -33,8 +33,8 @@ /* #define VIPS_DEBUG - */ #define DEBUG + */ #ifdef HAVE_CONFIG_H #include diff --git a/libvips/resample/thumbnail.c b/libvips/resample/thumbnail.c index 67a788ab..66374d1d 100644 --- a/libvips/resample/thumbnail.c +++ b/libvips/resample/thumbnail.c @@ -113,6 +113,11 @@ typedef struct _VipsThumbnail { */ int n_pages; + /* For HEIF, try to fetch the size of the stored thumbnail. + */ + int heif_thumbnail_width; + int heif_thumbnail_height; + } VipsThumbnail; typedef struct _VipsThumbnailClass { @@ -262,6 +267,28 @@ vips_thumbnail_get_tiff_pyramid( VipsThumbnail *thumbnail ) thumbnail->level_count = thumbnail->n_pages; } +/* This may not be a pyr tiff, so no error if we can't find the layers. + */ +static int +vips_thumbnail_get_heif_thumb_info( VipsThumbnail *thumbnail ) +{ + VipsThumbnailClass *class = VIPS_THUMBNAIL_GET_CLASS( thumbnail ); + + VipsImage *thumb; + + if( !(thumb = class->open( thumbnail, 1 )) ) + return( -1 ); + + if( thumb->Xsize < thumbnail->input_width ) { + thumbnail->heif_thumbnail_width = thumb->Xsize; + thumbnail->heif_thumbnail_height = thumb->Ysize; + } + + VIPS_UNREF( thumb ); + + return( 0 ); +} + /* Calculate the shrink factor, taking into account auto-rotate, the fit mode, * and so on. * @@ -418,6 +445,12 @@ vips_thumbnail_open( VipsThumbnail *thumbnail ) if( vips_isprefix( "VipsForeignLoadTiff", thumbnail->loader ) ) vips_thumbnail_get_tiff_pyramid( thumbnail ); + /* For heif, we need to fetch the thumbnail size, in case we can use + * that as the source. + */ + if( vips_isprefix( "VipsForeignLoadHeif", thumbnail->loader ) ) + vips_thumbnail_get_heif_thumb_info( thumbnail ); + factor = 1.0; if( vips_isprefix( "VipsForeignLoadJpeg", thumbnail->loader ) ) { @@ -450,6 +483,19 @@ vips_thumbnail_open( VipsThumbnail *thumbnail ) g_info( "loading webp with factor %g pre-shrink", factor ); } + else if( vips_isprefix( "VipsForeignLoadHeif", thumbnail->loader ) ) { + /* 'factor' is a gboolean which enables thumbnail load instead + * of image load. + * + * Use the thumbnail if it's larger than our target. + */ + if( thumbnail->heif_thumbnail_width >= thumbnail->width && + thumbnail->heif_thumbnail_height >= thumbnail->height ) + factor = 1.0; + else + factor = 0.0; + + } if( !(im = class->open( thumbnail, factor )) ) return( NULL ); @@ -864,6 +910,12 @@ vips_thumbnail_file_open( VipsThumbnail *thumbnail, double factor ) "page", (int) factor, NULL ) ); } + else if( vips_isprefix( "VipsForeignLoadHeif", thumbnail->loader ) ) { + return( vips_image_new_from_file( file->filename, + "access", VIPS_ACCESS_SEQUENTIAL, + "thumbnail", (int) factor, + NULL ) ); + } else { return( vips_image_new_from_file( file->filename, "access", VIPS_ACCESS_SEQUENTIAL, @@ -1052,6 +1104,13 @@ vips_thumbnail_buffer_open( VipsThumbnail *thumbnail, double factor ) "page", (int) factor, NULL ) ); } + else if( vips_isprefix( "VipsForeignLoadHeif", thumbnail->loader ) ) { + return( vips_image_new_from_buffer( + buffer->buf->data, buffer->buf->length, "", + "access", VIPS_ACCESS_SEQUENTIAL, + "thumbnail", (int) factor, + NULL ) ); + } else { return( vips_image_new_from_buffer( buffer->buf->data, buffer->buf->length, "",