diff --git a/ChangeLog b/ChangeLog index cc72ccf7..89763f00 100644 --- a/ChangeLog +++ b/ChangeLog @@ -7,6 +7,8 @@ - added vips_image_hasalpha() - added vips_thumbnail() / vips_thumbnail_buffer() - better >4gb detect for zip dzsave output [Felix Bünemann] +- all loaders have a @fail option, meaning fail on first warning, though it + only does anything for jpg, csv, openslide 11/11/16 started 8.4.4 - fix crash in vips.exe arg parsing on Windows, thanks Yury diff --git a/libvips/deprecated/im_csv2vips.c b/libvips/deprecated/im_csv2vips.c index 55900b93..a2bf48e0 100644 --- a/libvips/deprecated/im_csv2vips.c +++ b/libvips/deprecated/im_csv2vips.c @@ -76,7 +76,7 @@ im_csv2vips( const char *filename, IMAGE *out ) } if( vips__csv_read( name, out, - start_skip, lines, whitespace, separator ) ) + start_skip, lines, whitespace, separator, FALSE ) ) return( -1 ); return( 0 ); diff --git a/libvips/foreign/csv.c b/libvips/foreign/csv.c index 5ea4cbcf..95f71f18 100644 --- a/libvips/foreign/csv.c +++ b/libvips/foreign/csv.c @@ -172,7 +172,7 @@ skip_to_sep( FILE *fp, const char sepmap[256] ) */ static int read_double( FILE *fp, const char whitemap[256], const char sepmap[256], - int lineno, int colno, double *out ) + int lineno, int colno, double *out, gboolean fail ) { int ch; @@ -198,6 +198,8 @@ read_double( FILE *fp, const char whitemap[256], const char sepmap[256], vips_warn( "csv2vips", _( "error parsing number, line %d, column %d" ), lineno, colno ); + if( fail ) + return( EOF ); /* Step over the bad data to the next separator. */ @@ -222,7 +224,8 @@ read_csv( FILE *fp, VipsImage *out, int skip, int lines, const char *whitespace, const char *separator, - gboolean read_image ) + gboolean read_image, + gboolean fail ) { int i; char whitemap[256]; @@ -265,7 +268,7 @@ read_csv( FILE *fp, VipsImage *out, } for( columns = 0; (ch = read_double( fp, whitemap, sepmap, - skip + 1, columns + 1, &d )) == 0; + skip + 1, columns + 1, &d, fail )) == 0; columns++ ) ; (void) fsetpos( fp, &pos ); @@ -308,7 +311,7 @@ read_csv( FILE *fp, VipsImage *out, int colno = x + 1; ch = read_double( fp, whitemap, sepmap, - lineno, colno, &d ); + lineno, colno, &d, fail ); if( ch == EOF ) { vips_error( "csv2vips", _( "unexpected EOF, line %d col %d" ), @@ -342,13 +345,15 @@ read_csv( FILE *fp, VipsImage *out, int vips__csv_read( const char *filename, VipsImage *out, - int skip, int lines, const char *whitespace, const char *separator ) + int skip, int lines, const char *whitespace, const char *separator, + gboolean fail ) { FILE *fp; if( !(fp = vips__file_open_read( filename, NULL, TRUE )) ) return( -1 ); - if( read_csv( fp, out, skip, lines, whitespace, separator, TRUE ) ) { + if( read_csv( fp, out, + skip, lines, whitespace, separator, TRUE, fail ) ) { fclose( fp ); return( -1 ); } @@ -359,13 +364,15 @@ vips__csv_read( const char *filename, VipsImage *out, int vips__csv_read_header( const char *filename, VipsImage *out, - int skip, int lines, const char *whitespace, const char *separator ) + int skip, int lines, const char *whitespace, const char *separator, + gboolean fail ) { FILE *fp; if( !(fp = vips__file_open_read( filename, NULL, TRUE )) ) return( -1 ); - if( read_csv( fp, out, skip, lines, whitespace, separator, FALSE ) ) { + if( read_csv( fp, out, + skip, lines, whitespace, separator, FALSE, fail ) ) { fclose( fp ); return( -1 ); } diff --git a/libvips/foreign/csvload.c b/libvips/foreign/csvload.c index 9ee62135..59c37fe2 100644 --- a/libvips/foreign/csvload.c +++ b/libvips/foreign/csvload.c @@ -89,7 +89,8 @@ vips_foreign_load_csv_header( VipsForeignLoad *load ) VipsForeignLoadCsv *csv = (VipsForeignLoadCsv *) load; if( vips__csv_read_header( csv->filename, load->out, - csv->skip, csv->lines, csv->whitespace, csv->separator ) ) + csv->skip, csv->lines, csv->whitespace, csv->separator, + load->fail ) ) return( -1 ); VIPS_SETSTR( load->out->filename, csv->filename ); @@ -103,7 +104,8 @@ vips_foreign_load_csv_load( VipsForeignLoad *load ) VipsForeignLoadCsv *csv = (VipsForeignLoadCsv *) load; if( vips__csv_read( csv->filename, load->real, - csv->skip, csv->lines, csv->whitespace, csv->separator ) ) + csv->skip, csv->lines, csv->whitespace, csv->separator, + load->fail ) ) return( -1 ); return( 0 ); @@ -191,6 +193,7 @@ vips_foreign_load_csv_init( VipsForeignLoadCsv *csv ) * * @lines: read this many lines from file * * @whitespace: set of whitespace characters * * @separator: set of separator characters + * * @fail: %gboolean, fail on warnings * * Load a CSV (comma-separated values) file. The output image is always 1 * band (monochrome), #VIPS_FORMAT_DOUBLE. Use vips_bandfold() to turn @@ -218,6 +221,8 @@ vips_foreign_load_csv_init( VipsForeignLoadCsv *csv ) * @separator sets the characters that separate fields. * Default ;,tab. Separators are never run together. * + * Setting @fail to %TRUE makes the reader fail on any warnings. + * * See also: vips_image_new_from_file(), vips_bandfold(). * * Returns: 0 on success, -1 on error. diff --git a/libvips/foreign/foreign.c b/libvips/foreign/foreign.c index 3313b9e6..ea7d03e3 100644 --- a/libvips/foreign/foreign.c +++ b/libvips/foreign/foreign.c @@ -986,6 +986,13 @@ vips_foreign_load_class_init( VipsForeignLoadClass *class ) G_STRUCT_OFFSET( VipsForeignLoad, sequential ), FALSE ); + VIPS_ARG_BOOL( class, "fail", 11, + _( "Fail" ), + _( "Fail on first warning" ), + VIPS_ARGUMENT_OPTIONAL_INPUT, + G_STRUCT_OFFSET( VipsForeignLoad, fail ), + FALSE ); + } static void diff --git a/libvips/foreign/jpegload.c b/libvips/foreign/jpegload.c index 186fd28f..9e53914e 100644 --- a/libvips/foreign/jpegload.c +++ b/libvips/foreign/jpegload.c @@ -77,10 +77,6 @@ typedef struct _VipsForeignLoadJpeg { */ int shrink; - /* Fail on first warning. - */ - gboolean fail; - /* Autorotate using exif orientation tag. */ gboolean autorotate; @@ -144,13 +140,6 @@ vips_foreign_load_jpeg_class_init( VipsForeignLoadJpegClass *class ) G_STRUCT_OFFSET( VipsForeignLoadJpeg, shrink ), 1, 16, 1 ); - VIPS_ARG_BOOL( class, "fail", 11, - _( "Fail" ), - _( "Fail on first warning" ), - VIPS_ARGUMENT_OPTIONAL_INPUT, - G_STRUCT_OFFSET( VipsForeignLoadJpeg, fail ), - FALSE ); - VIPS_ARG_BOOL( class, "autorotate", 12, _( "Autorotate" ), _( "Rotate image using exif orientation" ), @@ -201,7 +190,7 @@ vips_foreign_load_jpeg_file_header( VipsForeignLoad *load ) VipsForeignLoadJpegFile *file = (VipsForeignLoadJpegFile *) load; if( vips__jpeg_read_file( file->filename, load->out, - TRUE, jpeg->shrink, jpeg->fail, FALSE, jpeg->autorotate ) ) + TRUE, jpeg->shrink, load->fail, FALSE, jpeg->autorotate ) ) return( -1 ); return( 0 ); @@ -214,7 +203,7 @@ vips_foreign_load_jpeg_file_load( VipsForeignLoad *load ) VipsForeignLoadJpegFile *file = (VipsForeignLoadJpegFile *) load; if( vips__jpeg_read_file( file->filename, load->real, - FALSE, jpeg->shrink, jpeg->fail, + FALSE, jpeg->shrink, load->fail, load->access == VIPS_ACCESS_SEQUENTIAL, jpeg->autorotate ) ) return( -1 ); @@ -283,7 +272,7 @@ vips_foreign_load_jpeg_buffer_header( VipsForeignLoad *load ) VipsForeignLoadJpegBuffer *buffer = (VipsForeignLoadJpegBuffer *) load; if( vips__jpeg_read_buffer( buffer->buf->data, buffer->buf->length, - load->out, TRUE, jpeg->shrink, jpeg->fail, FALSE, + load->out, TRUE, jpeg->shrink, load->fail, FALSE, jpeg->autorotate ) ) return( -1 ); @@ -297,7 +286,7 @@ vips_foreign_load_jpeg_buffer_load( VipsForeignLoad *load ) VipsForeignLoadJpegBuffer *buffer = (VipsForeignLoadJpegBuffer *) load; if( vips__jpeg_read_buffer( buffer->buf->data, buffer->buf->length, - load->real, FALSE, jpeg->shrink, jpeg->fail, + load->real, FALSE, jpeg->shrink, load->fail, load->access == VIPS_ACCESS_SEQUENTIAL, jpeg->autorotate ) ) return( -1 ); diff --git a/libvips/foreign/openslide2vips.c b/libvips/foreign/openslide2vips.c index bd94a196..27d8807b 100644 --- a/libvips/foreign/openslide2vips.c +++ b/libvips/foreign/openslide2vips.c @@ -115,6 +115,10 @@ typedef struct { */ int tile_width; int tile_height; + + /* Quit on warning. + */ + gboolean fail; } ReadSlide; int @@ -223,7 +227,7 @@ get_bounds( openslide_t *osr, VipsRect *rect ) static ReadSlide * readslide_new( const char *filename, VipsImage *out, - int level, gboolean autocrop, const char *associated ) + int level, gboolean autocrop, const char *associated, gboolean fail ) { ReadSlide *rslide; int64_t w, h; @@ -391,9 +395,9 @@ readslide_new( const char *filename, VipsImage *out, int vips__openslide_read_header( const char *filename, VipsImage *out, - int level, gboolean autocrop, char *associated ) + int level, gboolean autocrop, char *associated, gboolean fail ) { - if( !readslide_new( filename, out, level, autocrop, associated ) ) + if( !readslide_new( filename, out, level, autocrop, associated, fail ) ) return( -1 ); return( 0 ); @@ -475,13 +479,14 @@ vips__openslide_generate( VipsRegion *out, /* Only warn on error: we don't want to make the whole image unreadable * because of one broken tile. - * - * FIXME ... add a --fail option like jpegload */ error = openslide_get_error( rslide->osr ); - if( error ) + if( error ) { vips_warn( "openslide2vips", _( "reading region: %s" ), error ); + if( rslide->fail ) + return( -1 ); + } /* Since we are inside a cache, we know buf must be continuous. */ @@ -492,7 +497,7 @@ vips__openslide_generate( VipsRegion *out, int vips__openslide_read( const char *filename, VipsImage *out, - int level, gboolean autocrop ) + int level, gboolean autocrop, gboolean fail ) { ReadSlide *rslide; VipsImage *raw; @@ -505,7 +510,7 @@ vips__openslide_read( const char *filename, VipsImage *out, vips_object_local( out, raw ); if( !(rslide = readslide_new( filename, raw, - level, autocrop, NULL )) ) + level, autocrop, NULL, fail )) ) return( -1 ); if( vips_image_generate( raw, @@ -534,7 +539,7 @@ vips__openslide_read( const char *filename, VipsImage *out, int vips__openslide_read_associated( const char *filename, VipsImage *out, - const char *associated ) + const char *associated, gboolean fail ) { ReadSlide *rslide; VipsImage *raw; @@ -549,7 +554,8 @@ vips__openslide_read_associated( const char *filename, VipsImage *out, raw = vips_image_new_memory(); vips_object_local( out, raw ); - if( !(rslide = readslide_new( filename, raw, 0, FALSE, associated )) || + if( !(rslide = readslide_new( filename, raw, + 0, FALSE, associated, fail )) || vips_image_write_prepare( raw ) ) return( -1 ); buf = (uint32_t *) VIPS_IMAGE_ADDR( raw, 0, 0 ); diff --git a/libvips/foreign/openslideload.c b/libvips/foreign/openslideload.c index a02927fb..aef3eade 100644 --- a/libvips/foreign/openslideload.c +++ b/libvips/foreign/openslideload.c @@ -114,7 +114,7 @@ vips_foreign_load_openslide_header( VipsForeignLoad *load ) if( vips__openslide_read_header( openslide->filename, load->out, openslide->level, openslide->autocrop, - openslide->associated ) ) + openslide->associated, load->fail ) ) return( -1 ); VIPS_SETSTR( load->out->filename, openslide->filename ); @@ -129,13 +129,13 @@ vips_foreign_load_openslide_load( VipsForeignLoad *load ) if( !openslide->associated ) { if( vips__openslide_read( openslide->filename, load->real, - openslide->level, openslide->autocrop ) ) + openslide->level, openslide->autocrop, load->fail ) ) return( -1 ); } else { if( vips__openslide_read_associated( openslide->filename, load->real, - openslide->associated ) ) + openslide->associated, load->fail ) ) return( -1 ); } @@ -231,6 +231,7 @@ vips_foreign_load_openslide_init( VipsForeignLoadOpenslide *openslide ) * * @level: load this level * * @associated: load this associated image * * @autocrop: crop to image bounds + * * @fail: %gboolean, fail on warnings * * Read a virtual slide supported by the OpenSlide library into a VIPS image. * OpenSlide supports images in Aperio, Hamamatsu, MIRAX, Sakura, Trestle, @@ -250,6 +251,8 @@ vips_foreign_load_openslide_init( VipsForeignLoadOpenslide *openslide ) * * The output of this operator is always RGBA. * + * Setting @fail to %TRUE makes the reader fail on any warnings. + * * See also: vips_image_new_from_file(). * * Returns: 0 on success, -1 on error. diff --git a/libvips/foreign/pforeign.h b/libvips/foreign/pforeign.h index 95b63ea8..f0a8557a 100644 --- a/libvips/foreign/pforeign.h +++ b/libvips/foreign/pforeign.h @@ -87,9 +87,11 @@ int vips__analyze_read( const char *filename, VipsImage *out ); extern const char *vips__foreign_csv_suffs[]; int vips__csv_read( const char *filename, VipsImage *out, - int skip, int lines, const char *whitespace, const char *separator ); + int skip, int lines, const char *whitespace, const char *separator, + gboolean fail ); int vips__csv_read_header( const char *filename, VipsImage *out, - int skip, int lines, const char *whitespace, const char *separator ); + int skip, int lines, const char *whitespace, const char *separator, + gboolean fail ); int vips__csv_write( VipsImage *in, const char *filename, const char *separator ); @@ -215,11 +217,11 @@ int vips__webp_write_buffer( VipsImage *out, void **buf, size_t *len, int vips__openslide_isslide( const char *filename ); int vips__openslide_read_header( const char *filename, VipsImage *out, - int level, gboolean autocrop, char *associated ); + int level, gboolean autocrop, char *associated, gboolean fail ); int vips__openslide_read( const char *filename, VipsImage *out, - int level, gboolean autocrop ); + int level, gboolean autocrop, gboolean fail ); int vips__openslide_read_associated( const char *filename, VipsImage *out, - const char *associated ); + const char *associated, gboolean fail ); #ifdef __cplusplus } diff --git a/libvips/foreign/tiff.c b/libvips/foreign/tiff.c index ba82f4ee..07bf926d 100644 --- a/libvips/foreign/tiff.c +++ b/libvips/foreign/tiff.c @@ -67,6 +67,9 @@ vips__thandler_error( const char *module, const char *fmt, va_list ap ) vips_verror( module, fmt, ap ); } +/* It'd be nice to be able to support the @fail option for the tiff loader, but + * there's no easy way to do this, since libtiff has a global warning handler. + */ static void vips__thandler_warning( const char *module, const char *fmt, va_list ap ) { diff --git a/libvips/include/vips/foreign.h b/libvips/include/vips/foreign.h index 2245167b..cb510570 100644 --- a/libvips/include/vips/foreign.h +++ b/libvips/include/vips/foreign.h @@ -131,6 +131,10 @@ typedef struct _VipsForeignLoad { */ VipsForeignFlags flags; + /* Stop load on first warning. + */ + gboolean fail; + /* Deprecated and unused, just here for compat. */ gboolean sequential;