Skip to content

Commit 7a2b2f8

Browse files
authored
Merge pull request #1756 from libvips/heif-workaround
try to work around some broken heic images
2 parents 95a221d + 1099bd0 commit 7a2b2f8

File tree

1 file changed

+69
-20
lines changed

1 file changed

+69
-20
lines changed

libvips/foreign/heifload.c

Lines changed: 69 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
* - revise for new VipsSource API
1919
* 10/5/20
2020
* - deprecate autorotate -- it's too difficult to support properly
21+
* 31/7/20
22+
* - block broken thumbnails, if we can
2123
*/
2224

2325
/*
@@ -277,6 +279,71 @@ vips_foreign_load_heif_get_flags( VipsForeignLoad *load )
277279
return( VIPS_FOREIGN_SEQUENTIAL );
278280
}
279281

282+
/* We've selcted the page. Try to select the associated thumbnail instead,
283+
* if we can.
284+
*/
285+
static int
286+
vips_foreign_load_heif_set_thumbnail( VipsForeignLoadHeif *heif )
287+
{
288+
heif_item_id thumb_ids[1];
289+
int n_thumbs;
290+
struct heif_image_handle *thumb_handle;
291+
struct heif_image *thumb_img;
292+
struct heif_error error;
293+
double main_aspect;
294+
double thumb_aspect;
295+
296+
n_thumbs = heif_image_handle_get_list_of_thumbnail_IDs(
297+
heif->handle, thumb_ids, 1 );
298+
if( n_thumbs == 0 )
299+
return( 0 );
300+
301+
error = heif_image_handle_get_thumbnail( heif->handle,
302+
thumb_ids[0], &thumb_handle );
303+
if( error.code ) {
304+
vips__heif_error( &error );
305+
return( -1 );
306+
}
307+
308+
/* Just checking the width and height of the handle isn't
309+
* enough -- we have to experimentally decode it and test the
310+
* decoded dimensions.
311+
*/
312+
error = heif_decode_image( thumb_handle, &thumb_img,
313+
heif_colorspace_RGB,
314+
heif_chroma_interleaved_RGB,
315+
NULL );
316+
if( error.code ) {
317+
VIPS_FREEF( heif_image_handle_release, thumb_handle );
318+
vips__heif_error( &error );
319+
return( -1 );
320+
}
321+
322+
thumb_aspect = (double)
323+
heif_image_get_width( thumb_img, heif_channel_interleaved ) /
324+
heif_image_get_height( thumb_img, heif_channel_interleaved );
325+
326+
VIPS_FREEF( heif_image_release, thumb_img );
327+
328+
main_aspect = (double)
329+
heif_image_handle_get_width( heif->handle ) /
330+
heif_image_handle_get_height( heif->handle );
331+
332+
/* The bug we are working around has decoded thumbs as 512x512
333+
* with the main image as 6kx4k, so a 0.1 threshold is more
334+
* than tight enough to spot the error.
335+
*/
336+
if( fabs( main_aspect - thumb_aspect ) > 0.1 ) {
337+
VIPS_FREEF( heif_image_handle_release, thumb_handle );
338+
return( 0 );
339+
}
340+
341+
VIPS_FREEF( heif_image_handle_release, heif->handle );
342+
heif->handle = thumb_handle;
343+
344+
return( 0 );
345+
}
346+
280347
/* Select a page. If thumbnail is set, select the thumbnail for that page, if
281348
* there is one.
282349
*/
@@ -307,26 +374,8 @@ vips_foreign_load_heif_set_page( VipsForeignLoadHeif *heif,
307374
}
308375

309376
if( thumbnail ) {
310-
heif_item_id thumb_ids[1];
311-
int n_thumbs;
312-
struct heif_image_handle *thumb_handle;
313-
314-
n_thumbs = heif_image_handle_get_list_of_thumbnail_IDs(
315-
heif->handle, thumb_ids, 1 );
316-
317-
if( n_thumbs > 0 ) {
318-
error = heif_image_handle_get_thumbnail(
319-
heif->handle,
320-
thumb_ids[0], &thumb_handle );
321-
if( error.code ) {
322-
vips__heif_error( &error );
323-
return( -1 );
324-
}
325-
326-
VIPS_FREEF( heif_image_handle_release,
327-
heif->handle );
328-
heif->handle = thumb_handle;
329-
}
377+
if( vips_foreign_load_heif_set_thumbnail( heif ) )
378+
return( -1 );
330379

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

0 commit comments

Comments
 (0)