|
18 | 18 | * - revise for new VipsSource API
|
19 | 19 | * 10/5/20
|
20 | 20 | * - deprecate autorotate -- it's too difficult to support properly
|
| 21 | + * 31/7/20 |
| 22 | + * - block broken thumbnails, if we can |
21 | 23 | */
|
22 | 24 |
|
23 | 25 | /*
|
@@ -277,6 +279,71 @@ vips_foreign_load_heif_get_flags( VipsForeignLoad *load )
|
277 | 279 | return( VIPS_FOREIGN_SEQUENTIAL );
|
278 | 280 | }
|
279 | 281 |
|
| 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 | + |
280 | 347 | /* Select a page. If thumbnail is set, select the thumbnail for that page, if
|
281 | 348 | * there is one.
|
282 | 349 | */
|
@@ -307,26 +374,8 @@ vips_foreign_load_heif_set_page( VipsForeignLoadHeif *heif,
|
307 | 374 | }
|
308 | 375 |
|
309 | 376 | 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 ); |
330 | 379 |
|
331 | 380 | /* If we were asked to select the thumbnail, say we
|
332 | 381 | * did, even if there are no thumbnails and we just
|
|
0 commit comments