Skip to content

try to work around some broken heic images #1756

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Aug 1, 2020
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
89 changes: 69 additions & 20 deletions libvips/foreign/heifload.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
* - revise for new VipsSource API
* 10/5/20
* - deprecate autorotate -- it's too difficult to support properly
* 31/7/20
* - block broken thumbnails, if we can
*/

/*
Expand Down Expand Up @@ -277,6 +279,71 @@ vips_foreign_load_heif_get_flags( VipsForeignLoad *load )
return( VIPS_FOREIGN_SEQUENTIAL );
}

/* We've selcted the page. Try to select the associated thumbnail instead,
* if we can.
*/
static int
vips_foreign_load_heif_set_thumbnail( VipsForeignLoadHeif *heif )
{
heif_item_id thumb_ids[1];
int n_thumbs;
struct heif_image_handle *thumb_handle;
struct heif_image *thumb_img;
struct heif_error error;
double main_aspect;
double thumb_aspect;

n_thumbs = heif_image_handle_get_list_of_thumbnail_IDs(
heif->handle, thumb_ids, 1 );
if( n_thumbs == 0 )
return( 0 );

error = heif_image_handle_get_thumbnail( heif->handle,
thumb_ids[0], &thumb_handle );
if( error.code ) {
vips__heif_error( &error );
return( -1 );
}

/* Just checking the width and height of the handle isn't
* enough -- we have to experimentally decode it and test the
* decoded dimensions.
*/
error = heif_decode_image( thumb_handle, &thumb_img,
heif_colorspace_RGB,
heif_chroma_interleaved_RGB,
NULL );
if( error.code ) {
VIPS_FREEF( heif_image_handle_release, thumb_handle );
vips__heif_error( &error );
return( -1 );
}

thumb_aspect = (double)
heif_image_get_width( thumb_img, heif_channel_interleaved ) /
heif_image_get_height( thumb_img, heif_channel_interleaved );

VIPS_FREEF( heif_image_release, thumb_img );

main_aspect = (double)
heif_image_handle_get_width( heif->handle ) /
heif_image_handle_get_height( heif->handle );

/* The bug we are working around has decoded thumbs as 512x512
* with the main image as 6kx4k, so a 0.1 threshold is more
* than tight enough to spot the error.
*/
if( fabs( main_aspect - thumb_aspect ) > 0.1 ) {
VIPS_FREEF( heif_image_handle_release, thumb_handle );
return( 0 );
}

VIPS_FREEF( heif_image_handle_release, heif->handle );
heif->handle = thumb_handle;

return( 0 );
}

/* Select a page. If thumbnail is set, select the thumbnail for that page, if
* there is one.
*/
Expand Down Expand Up @@ -307,26 +374,8 @@ vips_foreign_load_heif_set_page( VipsForeignLoadHeif *heif,
}

if( thumbnail ) {
heif_item_id thumb_ids[1];
int n_thumbs;
struct heif_image_handle *thumb_handle;

n_thumbs = heif_image_handle_get_list_of_thumbnail_IDs(
heif->handle, thumb_ids, 1 );

if( n_thumbs > 0 ) {
error = heif_image_handle_get_thumbnail(
heif->handle,
thumb_ids[0], &thumb_handle );
if( error.code ) {
vips__heif_error( &error );
return( -1 );
}

VIPS_FREEF( heif_image_handle_release,
heif->handle );
heif->handle = thumb_handle;
}
if( vips_foreign_load_heif_set_thumbnail( heif ) )
return( -1 );

/* If we were asked to select the thumbnail, say we
* did, even if there are no thumbnails and we just
Expand Down