diff --git a/ChangeLog b/ChangeLog index eb7fd41e..6625fbfa 100644 --- a/ChangeLog +++ b/ChangeLog @@ -25,7 +25,7 @@ - add compute reordering, plus some new API to support it: vips_reorder_margin_hint() and vips_reorder_prepare_many(), thanks aferrero2707 -- kick load operations from cache on read error, thanks gaillard +- kick jpg, tif, png load operations from cache on read error, thanks gaillard 8/12/16 started 8.4.5 - allow libgsf-1.14.26 to help centos, thanks tdiprima diff --git a/libvips/foreign/fits.c b/libvips/foreign/fits.c index dac90adb..bf25aa1e 100644 --- a/libvips/foreign/fits.c +++ b/libvips/foreign/fits.c @@ -26,6 +26,8 @@ * 4/1/17 * - load to equivalent data type, not raw image data type ... improves * support for BSCALE / BZERO settings + * 17/1/17 + * - invalidate operation on read error */ /* @@ -360,6 +362,25 @@ vips__fits_read_header( const char *filename, VipsImage *out ) return( 0 ); } +static int +vips_fits_read_subset( VipsFits *fits, + long fpixel[MAX_DIMENSIONS], long lpixel[MAX_DIMENSIONS], + long inc[MAX_DIMENSIONS], VipsPel *q ) +{ + int status; + + if( fits_read_subset( fits->fptr, fits->datatype, + fpixel, lpixel, inc, + NULL, q, NULL, &status ) ) { + vips_fits_error( status ); + vips_foreign_load_invalidate( fits->image ); + + return( -1 ); + } + + return( 0 ); +} + static int fits2vips_generate( VipsRegion *out, void *seq, void *a, void *b, gboolean *stop ) @@ -369,14 +390,11 @@ fits2vips_generate( VipsRegion *out, VipsPel *q; int z; - int status; long fpixel[MAX_DIMENSIONS]; long lpixel[MAX_DIMENSIONS]; long inc[MAX_DIMENSIONS]; - status = 0; - VIPS_DEBUG_MSG( "fits2vips_generate: " "generating left = %d, top = %d, width = %d, height = %d\n", r->left, r->top, r->width, r->height ); @@ -407,10 +425,7 @@ fits2vips_generate( VipsRegion *out, /* Break on ffgsv() for this call. */ g_mutex_lock( fits->lock ); - if( fits_read_subset( fits->fptr, fits->datatype, - fpixel, lpixel, inc, - NULL, q, NULL, &status ) ) { - vips_fits_error( status ); + if( vips_fits_read_subset( fits, fpixel, lpixel, inc, q ) ) { g_mutex_unlock( fits->lock ); return( -1 ); } @@ -440,10 +455,8 @@ fits2vips_generate( VipsRegion *out, /* Break on ffgsv() for this call. */ g_mutex_lock( fits->lock ); - if( fits_read_subset( fits->fptr, fits->datatype, - fpixel, lpixel, inc, - NULL, q, NULL, &status ) ) { - vips_fits_error( status ); + if( vips_fits_read_subset( fits, + fpixel, lpixel, inc, q ) ) { g_mutex_unlock( fits->lock ); return( -1 ); } diff --git a/libvips/foreign/foreign.c b/libvips/foreign/foreign.c index a661a222..1c38a0f0 100644 --- a/libvips/foreign/foreign.c +++ b/libvips/foreign/foreign.c @@ -1021,12 +1021,12 @@ vips_foreign_load_init( VipsForeignLoad *load ) * * Loaders can call this on the image they are making if they see a read error * from the load library. It signals "invalidate" on the load operation and - * will cause it for be dropped from ache. + * will cause it for be dropped from cache. * - * If we know a file will cause a read error, we don't want to cache the error - * operation, we want to make sure the image will really be opened again if our - * caller tries again. For example, a broken file might be replaced by a - * working one. + * If we know a file will cause a read error, we don't want to cache the + * failing operation, we want to make sure the image will really be opened + * again if our caller tries again. For example, a broken file might be + * replaced by a working one. */ void vips_foreign_load_invalidate( VipsImage *image ) diff --git a/libvips/foreign/jpeg2vips.c b/libvips/foreign/jpeg2vips.c index 5c127041..280601cb 100644 --- a/libvips/foreign/jpeg2vips.c +++ b/libvips/foreign/jpeg2vips.c @@ -77,15 +77,14 @@ * 11/7/16 * - new --fail handling * 07/09/16 - * - Don't use the exif resolution if x_resolution / y_resolution / + * - don't use the exif resolution if x_resolution / y_resolution / * resolution_unit is missing -<<<<<<< HEAD * 7/11/16 * - exif handling moved out to exif.c -======= * 4/1/17 - * - Don't warn for missing exif res, since we fall back to jfif now ->>>>>>> master + * - don't warn for missing exif res, since we fall back to jfif now + * 17/1/17 + * - invalidate operation on read error */ /* diff --git a/libvips/foreign/tiff2vips.c b/libvips/foreign/tiff2vips.c index 5fae35ce..b1733c9c 100644 --- a/libvips/foreign/tiff2vips.c +++ b/libvips/foreign/tiff2vips.c @@ -169,6 +169,8 @@ * - add autorotate support * 17/11/16 * - add multi-page read + * 17/1/17 + * - invalidate operation on read error */ /* @@ -437,16 +439,17 @@ get_orientation( TIFF *tiff ) } static int -strip_read( TIFF *tiff, int strip, tdata_t buf ) +rtiff_strip_read( Rtiff *rtiff, int strip, tdata_t buf ) { tsize_t length; #ifdef DEBUG - printf( "strip_read: reading strip %d\n", strip ); + printf( "rtiff_strip_read: reading strip %d\n", strip ); #endif /*DEBUG*/ - length = TIFFReadEncodedStrip( tiff, strip, buf, (tsize_t) -1 ); + length = TIFFReadEncodedStrip( rtiff->tiff, strip, buf, (tsize_t) -1 ); if( length == -1 ) { + vips_foreign_load_invalidate( rtiff->out ); vips_error( "tiff2vips", "%s", _( "read error" ) ); return( -1 ); } @@ -1344,6 +1347,17 @@ rtiff_seq_start( VipsImage *out, void *a, void *b ) return( (void *) buf ); } +static int +rtiff_read_tile( Rtiff *rtiff, tdata_t *buf, int x, int y ) +{ + if( TIFFReadTile( rtiff->tiff, buf, x, y, 0, 0 ) < 0 ) { + vips_foreign_load_invalidate( rtiff->out ); + return( -1 ); + } + + return( 0 ); +} + /* Paint a tile from the file. This is a * special-case for when a region is exactly a tiff tile, and pixels need no * conversion. In this case, libtiff can read tiles directly to our output @@ -1370,9 +1384,9 @@ rtiff_fill_region_aligned( VipsRegion *out, void *seq, void *a, void *b ) /* Read that tile directly into the vips tile. */ - if( TIFFReadTile( rtiff->tiff, - VIPS_REGION_ADDR( out, r->left, r->top ), - r->left, r->top, 0, 0 ) < 0 ) { + if( rtiff_read_tile( rtiff, + (tdata_t *) VIPS_REGION_ADDR( out, r->left, r->top ), + r->left, r->top ) ) { VIPS_GATE_STOP( "rtiff_fill_region_aligned: work" ); return( -1 ); } @@ -1436,8 +1450,7 @@ rtiff_fill_region( VipsRegion *out, void *seq, void *a, void *b, gboolean *stop int ys = (page_y / tile_height) * tile_height; if( rtiff_set_page( rtiff, page_no ) || - TIFFReadTile( rtiff->tiff, - buf, xs, ys, 0, 0 ) < 0 ) { + rtiff_read_tile( rtiff, buf, xs, ys ) ) { VIPS_GATE_STOP( "rtiff_fill_region: work" ); return( -1 ); } @@ -1640,7 +1653,7 @@ rtiff_strip_read_interleaved( Rtiff *rtiff, tstrip_t strip, tdata_t buf ) VipsPel *p; VipsPel *q; - if( strip_read( rtiff->tiff, + if( rtiff_strip_read( rtiff, strips_per_plane * i + strip, rtiff->plane_buf ) ) return( -1 ); @@ -1657,7 +1670,7 @@ rtiff_strip_read_interleaved( Rtiff *rtiff, tstrip_t strip, tdata_t buf ) } } else { - if( strip_read( rtiff->tiff, strip, buf ) ) + if( rtiff_strip_read( rtiff, strip, buf ) ) return( -1 ); } diff --git a/libvips/foreign/vipspng.c b/libvips/foreign/vipspng.c index 3e85ab32..cbd6b23f 100644 --- a/libvips/foreign/vipspng.c +++ b/libvips/foreign/vipspng.c @@ -57,7 +57,8 @@ * fd during file read, handy for large numbers of input images * 31/7/16 * - support --strip option - * + * 17/1/17 + * - invalidate operation on read error */ /* @@ -512,6 +513,11 @@ png2vips_generate( VipsRegion *or, if( !setjmp( png_jmpbuf( read->pPng ) ) ) png_read_row( read->pPng, q, NULL ); else { + /* We've failed to read some pixels. Knock this + * operation out of cache. + */ + vips_foreign_load_invalidate( read->out ); + #ifdef DEBUG printf( "png2vips_generate: png_read_row() failed, " "line %d\n", r->top + y );