move @fail from jpegload into the base load class

and add fail support to csv and openslide

see https://github.com/jcupitt/libvips/issues/546
This commit is contained in:
John Cupitt 2016-11-12 15:33:35 +00:00
parent e72d145ae9
commit bb0a6643f9
11 changed files with 72 additions and 44 deletions

View File

@ -7,6 +7,8 @@
- added vips_image_hasalpha() - added vips_image_hasalpha()
- added vips_thumbnail() / vips_thumbnail_buffer() - added vips_thumbnail() / vips_thumbnail_buffer()
- better >4gb detect for zip dzsave output [Felix Bünemann] - 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 11/11/16 started 8.4.4
- fix crash in vips.exe arg parsing on Windows, thanks Yury - fix crash in vips.exe arg parsing on Windows, thanks Yury

View File

@ -76,7 +76,7 @@ im_csv2vips( const char *filename, IMAGE *out )
} }
if( vips__csv_read( name, out, if( vips__csv_read( name, out,
start_skip, lines, whitespace, separator ) ) start_skip, lines, whitespace, separator, FALSE ) )
return( -1 ); return( -1 );
return( 0 ); return( 0 );

View File

@ -172,7 +172,7 @@ skip_to_sep( FILE *fp, const char sepmap[256] )
*/ */
static int static int
read_double( FILE *fp, const char whitemap[256], const char sepmap[256], 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; int ch;
@ -198,6 +198,8 @@ read_double( FILE *fp, const char whitemap[256], const char sepmap[256],
vips_warn( "csv2vips", vips_warn( "csv2vips",
_( "error parsing number, line %d, column %d" ), _( "error parsing number, line %d, column %d" ),
lineno, colno ); lineno, colno );
if( fail )
return( EOF );
/* Step over the bad data to the next separator. /* Step over the bad data to the next separator.
*/ */
@ -222,7 +224,8 @@ read_csv( FILE *fp, VipsImage *out,
int skip, int skip,
int lines, int lines,
const char *whitespace, const char *separator, const char *whitespace, const char *separator,
gboolean read_image ) gboolean read_image,
gboolean fail )
{ {
int i; int i;
char whitemap[256]; char whitemap[256];
@ -265,7 +268,7 @@ read_csv( FILE *fp, VipsImage *out,
} }
for( columns = 0; for( columns = 0;
(ch = read_double( fp, whitemap, sepmap, (ch = read_double( fp, whitemap, sepmap,
skip + 1, columns + 1, &d )) == 0; skip + 1, columns + 1, &d, fail )) == 0;
columns++ ) columns++ )
; ;
(void) fsetpos( fp, &pos ); (void) fsetpos( fp, &pos );
@ -308,7 +311,7 @@ read_csv( FILE *fp, VipsImage *out,
int colno = x + 1; int colno = x + 1;
ch = read_double( fp, whitemap, sepmap, ch = read_double( fp, whitemap, sepmap,
lineno, colno, &d ); lineno, colno, &d, fail );
if( ch == EOF ) { if( ch == EOF ) {
vips_error( "csv2vips", vips_error( "csv2vips",
_( "unexpected EOF, line %d col %d" ), _( "unexpected EOF, line %d col %d" ),
@ -342,13 +345,15 @@ read_csv( FILE *fp, VipsImage *out,
int int
vips__csv_read( const char *filename, VipsImage *out, 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; FILE *fp;
if( !(fp = vips__file_open_read( filename, NULL, TRUE )) ) if( !(fp = vips__file_open_read( filename, NULL, TRUE )) )
return( -1 ); 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 ); fclose( fp );
return( -1 ); return( -1 );
} }
@ -359,13 +364,15 @@ vips__csv_read( const char *filename, VipsImage *out,
int int
vips__csv_read_header( const char *filename, VipsImage *out, 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; FILE *fp;
if( !(fp = vips__file_open_read( filename, NULL, TRUE )) ) if( !(fp = vips__file_open_read( filename, NULL, TRUE )) )
return( -1 ); 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 ); fclose( fp );
return( -1 ); return( -1 );
} }

View File

@ -89,7 +89,8 @@ vips_foreign_load_csv_header( VipsForeignLoad *load )
VipsForeignLoadCsv *csv = (VipsForeignLoadCsv *) load; VipsForeignLoadCsv *csv = (VipsForeignLoadCsv *) load;
if( vips__csv_read_header( csv->filename, load->out, 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 ); return( -1 );
VIPS_SETSTR( load->out->filename, csv->filename ); VIPS_SETSTR( load->out->filename, csv->filename );
@ -103,7 +104,8 @@ vips_foreign_load_csv_load( VipsForeignLoad *load )
VipsForeignLoadCsv *csv = (VipsForeignLoadCsv *) load; VipsForeignLoadCsv *csv = (VipsForeignLoadCsv *) load;
if( vips__csv_read( csv->filename, load->real, 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( -1 );
return( 0 ); return( 0 );
@ -191,6 +193,7 @@ vips_foreign_load_csv_init( VipsForeignLoadCsv *csv )
* * @lines: read this many lines from file * * @lines: read this many lines from file
* * @whitespace: set of whitespace characters * * @whitespace: set of whitespace characters
* * @separator: set of separator characters * * @separator: set of separator characters
* * @fail: %gboolean, fail on warnings
* *
* Load a CSV (comma-separated values) file. The output image is always 1 * Load a CSV (comma-separated values) file. The output image is always 1
* band (monochrome), #VIPS_FORMAT_DOUBLE. Use vips_bandfold() to turn * 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. * @separator sets the characters that separate fields.
* Default ;,<emphasis>tab</emphasis>. Separators are never run together. * Default ;,<emphasis>tab</emphasis>. 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(). * See also: vips_image_new_from_file(), vips_bandfold().
* *
* Returns: 0 on success, -1 on error. * Returns: 0 on success, -1 on error.

View File

@ -986,6 +986,13 @@ vips_foreign_load_class_init( VipsForeignLoadClass *class )
G_STRUCT_OFFSET( VipsForeignLoad, sequential ), G_STRUCT_OFFSET( VipsForeignLoad, sequential ),
FALSE ); FALSE );
VIPS_ARG_BOOL( class, "fail", 11,
_( "Fail" ),
_( "Fail on first warning" ),
VIPS_ARGUMENT_OPTIONAL_INPUT,
G_STRUCT_OFFSET( VipsForeignLoad, fail ),
FALSE );
} }
static void static void

View File

@ -77,10 +77,6 @@ typedef struct _VipsForeignLoadJpeg {
*/ */
int shrink; int shrink;
/* Fail on first warning.
*/
gboolean fail;
/* Autorotate using exif orientation tag. /* Autorotate using exif orientation tag.
*/ */
gboolean autorotate; gboolean autorotate;
@ -144,13 +140,6 @@ vips_foreign_load_jpeg_class_init( VipsForeignLoadJpegClass *class )
G_STRUCT_OFFSET( VipsForeignLoadJpeg, shrink ), G_STRUCT_OFFSET( VipsForeignLoadJpeg, shrink ),
1, 16, 1 ); 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, VIPS_ARG_BOOL( class, "autorotate", 12,
_( "Autorotate" ), _( "Autorotate" ),
_( "Rotate image using exif orientation" ), _( "Rotate image using exif orientation" ),
@ -201,7 +190,7 @@ vips_foreign_load_jpeg_file_header( VipsForeignLoad *load )
VipsForeignLoadJpegFile *file = (VipsForeignLoadJpegFile *) load; VipsForeignLoadJpegFile *file = (VipsForeignLoadJpegFile *) load;
if( vips__jpeg_read_file( file->filename, load->out, 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( -1 );
return( 0 ); return( 0 );
@ -214,7 +203,7 @@ vips_foreign_load_jpeg_file_load( VipsForeignLoad *load )
VipsForeignLoadJpegFile *file = (VipsForeignLoadJpegFile *) load; VipsForeignLoadJpegFile *file = (VipsForeignLoadJpegFile *) load;
if( vips__jpeg_read_file( file->filename, load->real, 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 ) ) load->access == VIPS_ACCESS_SEQUENTIAL, jpeg->autorotate ) )
return( -1 ); return( -1 );
@ -283,7 +272,7 @@ vips_foreign_load_jpeg_buffer_header( VipsForeignLoad *load )
VipsForeignLoadJpegBuffer *buffer = (VipsForeignLoadJpegBuffer *) load; VipsForeignLoadJpegBuffer *buffer = (VipsForeignLoadJpegBuffer *) load;
if( vips__jpeg_read_buffer( buffer->buf->data, buffer->buf->length, 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 ) ) jpeg->autorotate ) )
return( -1 ); return( -1 );
@ -297,7 +286,7 @@ vips_foreign_load_jpeg_buffer_load( VipsForeignLoad *load )
VipsForeignLoadJpegBuffer *buffer = (VipsForeignLoadJpegBuffer *) load; VipsForeignLoadJpegBuffer *buffer = (VipsForeignLoadJpegBuffer *) load;
if( vips__jpeg_read_buffer( buffer->buf->data, buffer->buf->length, 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 ) ) load->access == VIPS_ACCESS_SEQUENTIAL, jpeg->autorotate ) )
return( -1 ); return( -1 );

View File

@ -115,6 +115,10 @@ typedef struct {
*/ */
int tile_width; int tile_width;
int tile_height; int tile_height;
/* Quit on warning.
*/
gboolean fail;
} ReadSlide; } ReadSlide;
int int
@ -223,7 +227,7 @@ get_bounds( openslide_t *osr, VipsRect *rect )
static ReadSlide * static ReadSlide *
readslide_new( const char *filename, VipsImage *out, 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; ReadSlide *rslide;
int64_t w, h; int64_t w, h;
@ -391,9 +395,9 @@ readslide_new( const char *filename, VipsImage *out,
int int
vips__openslide_read_header( const char *filename, VipsImage *out, 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( -1 );
return( 0 ); 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 /* Only warn on error: we don't want to make the whole image unreadable
* because of one broken tile. * because of one broken tile.
*
* FIXME ... add a --fail option like jpegload
*/ */
error = openslide_get_error( rslide->osr ); error = openslide_get_error( rslide->osr );
if( error ) if( error ) {
vips_warn( "openslide2vips", vips_warn( "openslide2vips",
_( "reading region: %s" ), error ); _( "reading region: %s" ), error );
if( rslide->fail )
return( -1 );
}
/* Since we are inside a cache, we know buf must be continuous. /* Since we are inside a cache, we know buf must be continuous.
*/ */
@ -492,7 +497,7 @@ vips__openslide_generate( VipsRegion *out,
int int
vips__openslide_read( const char *filename, VipsImage *out, vips__openslide_read( const char *filename, VipsImage *out,
int level, gboolean autocrop ) int level, gboolean autocrop, gboolean fail )
{ {
ReadSlide *rslide; ReadSlide *rslide;
VipsImage *raw; VipsImage *raw;
@ -505,7 +510,7 @@ vips__openslide_read( const char *filename, VipsImage *out,
vips_object_local( out, raw ); vips_object_local( out, raw );
if( !(rslide = readslide_new( filename, raw, if( !(rslide = readslide_new( filename, raw,
level, autocrop, NULL )) ) level, autocrop, NULL, fail )) )
return( -1 ); return( -1 );
if( vips_image_generate( raw, if( vips_image_generate( raw,
@ -534,7 +539,7 @@ vips__openslide_read( const char *filename, VipsImage *out,
int int
vips__openslide_read_associated( const char *filename, VipsImage *out, vips__openslide_read_associated( const char *filename, VipsImage *out,
const char *associated ) const char *associated, gboolean fail )
{ {
ReadSlide *rslide; ReadSlide *rslide;
VipsImage *raw; VipsImage *raw;
@ -549,7 +554,8 @@ vips__openslide_read_associated( const char *filename, VipsImage *out,
raw = vips_image_new_memory(); raw = vips_image_new_memory();
vips_object_local( out, raw ); 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 ) ) vips_image_write_prepare( raw ) )
return( -1 ); return( -1 );
buf = (uint32_t *) VIPS_IMAGE_ADDR( raw, 0, 0 ); buf = (uint32_t *) VIPS_IMAGE_ADDR( raw, 0, 0 );

View File

@ -114,7 +114,7 @@ vips_foreign_load_openslide_header( VipsForeignLoad *load )
if( vips__openslide_read_header( openslide->filename, load->out, if( vips__openslide_read_header( openslide->filename, load->out,
openslide->level, openslide->autocrop, openslide->level, openslide->autocrop,
openslide->associated ) ) openslide->associated, load->fail ) )
return( -1 ); return( -1 );
VIPS_SETSTR( load->out->filename, openslide->filename ); VIPS_SETSTR( load->out->filename, openslide->filename );
@ -129,13 +129,13 @@ vips_foreign_load_openslide_load( VipsForeignLoad *load )
if( !openslide->associated ) { if( !openslide->associated ) {
if( vips__openslide_read( openslide->filename, load->real, if( vips__openslide_read( openslide->filename, load->real,
openslide->level, openslide->autocrop ) ) openslide->level, openslide->autocrop, load->fail ) )
return( -1 ); return( -1 );
} }
else { else {
if( vips__openslide_read_associated( if( vips__openslide_read_associated(
openslide->filename, load->real, openslide->filename, load->real,
openslide->associated ) ) openslide->associated, load->fail ) )
return( -1 ); return( -1 );
} }
@ -231,6 +231,7 @@ vips_foreign_load_openslide_init( VipsForeignLoadOpenslide *openslide )
* * @level: load this level * * @level: load this level
* * @associated: load this associated image * * @associated: load this associated image
* * @autocrop: crop to image bounds * * @autocrop: crop to image bounds
* * @fail: %gboolean, fail on warnings
* *
* Read a virtual slide supported by the OpenSlide library into a VIPS image. * Read a virtual slide supported by the OpenSlide library into a VIPS image.
* OpenSlide supports images in Aperio, Hamamatsu, MIRAX, Sakura, Trestle, * 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. * 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(). * See also: vips_image_new_from_file().
* *
* Returns: 0 on success, -1 on error. * Returns: 0 on success, -1 on error.

View File

@ -87,9 +87,11 @@ int vips__analyze_read( const char *filename, VipsImage *out );
extern const char *vips__foreign_csv_suffs[]; extern const char *vips__foreign_csv_suffs[];
int vips__csv_read( const char *filename, 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 );
int vips__csv_read_header( 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 );
int vips__csv_write( VipsImage *in, const char *filename, int vips__csv_write( VipsImage *in, const char *filename,
const char *separator ); 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_isslide( const char *filename );
int vips__openslide_read_header( 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 );
int vips__openslide_read( const char *filename, VipsImage *out, 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, int vips__openslide_read_associated( const char *filename, VipsImage *out,
const char *associated ); const char *associated, gboolean fail );
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -67,6 +67,9 @@ vips__thandler_error( const char *module, const char *fmt, va_list ap )
vips_verror( module, fmt, 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 static void
vips__thandler_warning( const char *module, const char *fmt, va_list ap ) vips__thandler_warning( const char *module, const char *fmt, va_list ap )
{ {

View File

@ -131,6 +131,10 @@ typedef struct _VipsForeignLoad {
*/ */
VipsForeignFlags flags; VipsForeignFlags flags;
/* Stop load on first warning.
*/
gboolean fail;
/* Deprecated and unused, just here for compat. /* Deprecated and unused, just here for compat.
*/ */
gboolean sequential; gboolean sequential;